Reputation: 2851
I am newbie in the process usage under C, I have the question related to the linux behavior of file descriptors in the child process.
I have found out the information that the file descriptors are shared between the child and parent process, also that file descriptors with numbers 0,1,2 are standard input output and error, so I thought that if I fork the process I will have same input and output directories, however when i change it in the child processthey are not changed in the parent process. My question is, does it work for every file descriptor so if I decide to lets say overwrite file descriptor number 100 in the child process it will be different in the child and parent, or only file descriptors 0, 1, 2 are considered special.
Best regards
Upvotes: 1
Views: 2401
Reputation: 881113
POSIX threading actually has little to do specifically with fork
so I assume you're talking about processes rather than threads. With threads, there is no concept of parent and child and both share the same data.
For processes, every process has its own set of file descriptors that are unique to it, a small non-negative number (not file handles, which is a concept of C).
However, these file descriptors all point to entries in a shared pool (inside the kernel, for example). This allows all processes to have their own standard input, output and error (descriptors 0, 1 and 2) but with the possibility they may refer to the same "backing file".
So, when your process forks, it gets its own file descriptors but they point to the same shared pool entries as the parent.
If the child then goes and closes its file descriptor and reopens it to point somewhere else, that affects only the child, not the parent.
So let's say you have three processes as the result of two forks, and process C has closed and reopened its standard output to go to a file. Here's a (sort of) graphical indication as to the situation you're in:
Individual processes Shared pool
+------+ +------------------+
Process A | fd 1 | ----+----> | maps to /dev/tty |
+------+ | +------------------+
Process B | fd 1 | ----+
+------+ +------------------+
Process C | fd 1 | ---------> | maps to new file |
+------+ +------------------+
This behaviour is in no way special for the three standard descriptors, it applies to them all. In fact, descriptors not only survive a fork
, they also (usually) survive an exec
, something that makes redirection work under UNIX-like operating systems. You have to explicitly mark a descriptor if you want to have it automatically closed on exec
.
Upvotes: 7
Reputation: 239011
A child process gets a copy of the parent's open file table at the time of fork()
, but after that point any changes in either the parent or the child (eg opening a new file descriptor or closing an existing one) are not reflected in the other. There is nothing special about file descriptors 0, 1 and 2 in this regard.
Note however that even though the open file table (ie. set of file descriptors) is copied, the open files referred to by those descriptors are not. This means that updates to the open file (eg. changing the current file position with lseek()
) affect both processes.
It is a different matter for threads. Threads in the same process share the same open file table, so changes in one thread are seen by all threads. Again, there is nothing special about file descriptors 0, 1 and 2 in this regard.
Upvotes: 1
Reputation: 409136
You can think of file descriptors as indexes into an array. So there is nothing special about the descriptors for standard input/output/error really.
And once you've forked the process there will be two of these arrays, one for the parent and one for the child. They will both the the same to start with since it's copied, but once the different processes start to open and close other file descriptors they will start to diverge.
Upvotes: 1