Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

stdin, stdout and stderr are shared between?

I am trying to understand the behavior of the three streams - stdout, stdin and stderr. I couldn't get the answer from any textbook, so I came here.

I know that these three are stored in file descriptor table with file descriptors 0 (stdin), 1 (stdout) and 2 (stderr). I am also aware that these are not merely file descriptors but I/O streams which can be redirected. Ok, so how about sharing?

Consider the three cases:

  1. When a fork() is called : The child process and parent process shares file descriptors, but do they have the same stdin, stdout and stderr ?
  2. When a thread is created : Threads share file descriptors, but I/O streams?
  3. When execl() is called : In this case the present process image is overwritten with new process image. If I do execl("./a.out", "a.out", NULL); , then will this new executable get a freshcopy of stdin, stderr and stdout?

All wise answers are welcome.

like image 272
0aslam0 Avatar asked Nov 01 '14 08:11

0aslam0


People also ask

What is stdin and stdout and stderr?

stdin − It stands for standard input, and is used for taking text as an input. stdout − It stands for standard output, and is used to text output of any command you type in the terminal, and then that output is stored in the stdout stream. stderr − It stands for standard error.

Is stdout shared between processes?

Yes they share the same location.

What is stdout stdin and stderr in C?

In computer programming, standard streams are interconnected input and output communication channels between a computer program and its environment when it begins execution. The three input/output (I/O) connections are called standard input (stdin), standard output (stdout) and standard error (stderr).

Where is stdin stored?

In Linux, you can generally find stdin through the /proc file system in /proc/self/fd/0 , and stdout is /proc/self/fd/1 .


1 Answers

In order to understand what's going on, consider that these are communication channels across the process boundaries. I'll avoid calling them streams, because those are used in different contexts, but they are related.

Now, firstly, the filedescriptor is just an index into a process-specific table that represents these channels, they are basically a kind of opaque handle. However, here is the first answer: Since threads are part of a process, they also share these descriptors, so if you write from two threads into the same channel, it leaves through the same channel, so outside of the process, the two threads are indistinguishable.

Then, when fork() is called, the process is effectively copied. This is done with copy-on-write optimizations, but still, it means that they also have different tables representing these communication channels. The entry with index 2 in one process is not the same as the one with index 2 in the fork. This is the same for any structure that is inside the process, if you created a C FILE* or a C++ std::stream on top of one, it gets copied, too, along with the other data.

When execl() is called, the process still "owns" certain channels to the outside. These are assigned to it from the OS which manages processes. This means that the index 2 can still be used to communicate with the outside world. On startup, the runtime library will then create e.g. the FILE* for use in C for the three well-known channels stdin, stdout and stderr.

The question that remains is what happens when a process is forked to the channels to the outside. Here, the answer is simple, either the channel is closed or inherited, which can be configured on a per-channel base. If it is inherited, it remains usable in the child process. Anything written to an inherited channel will end up wherever the output from the parent process would have ended up, too.

Concerning the stdin of a forked process, I'm actually not sure, I think that the input is by default one of those that are closed, because sending input to multiple targets doesn't make sense. Also, I never found the need to actually process input from stdin in a child process, unless that input was specifically provided by the parent process (similar to pipes in the shell, although those are siblings rather than parent and child).

Note: I'm not sure if this description is clear, please don't hesitate to ask and I will try to improve things for your understanding.

like image 84
Ulrich Eckhardt Avatar answered Oct 18 '22 21:10

Ulrich Eckhardt