When we fork() a process, the child process inherits the file descriptors. The question is, why?

As I am seeing it, sharing the file descriptor is a headache when every process is trying to keep track of where the r/w pointer is.

Why was this design decision taken?

  • It's simpler than manually passing on stdin/stdout/stderr to every process you fork off, I'd think – muru Jan 31 '18 at 10:25
  • A greater headache would exist without it. No standard input & output with all their possible redirections, and no pipes either! – VPfB Jan 31 '18 at 10:50
  • why would every process be trying to keep track of where the pointer is? two things reading from stdin would only conflict with the other, and the output streams are appended to – thrig Jan 31 '18 at 14:55

POSIX explains the reasoning thus:

There are two reasons why POSIX programmers call fork(). One reason is to create a new thread of control within the same program (which was originally only possible in POSIX by creating a new process); the other is to create a new process running a different program. In the latter case, the call to fork() is soon followed by a call to one of the exec functions.

When fork() is used as a “poor-man’s threading”, it makes sense to copy the file descriptors. That use-case has to continue to be supported, so this feature will remain...


Consider a shell snippet

{ somecmd; othercommand *.txt; } > outputfile

The shell opens outputfile once, when starting the redirection, and then passes the file handle to the somecmd and othercmd, processes it forks off. Given the grouping, the user might not be wrong to expect to get the output of both commands to end up in outputfile, the same way they would end up on the screen. (That would be the same if the { } group was a shell script instead.)

If the file position was independent for all processes, the output from othercommand would clobber the output of somecmd. If a fork reset the position on the file handle, the shell would have no way of passing othercommand a handle that pointed at the end of outputfile (as it was after somecmd). We'd have to use a pipe to collect the output from both commands (they're position-agnostic anyway), and have another program concatenate the output from the two:

{ somecmd; othercommand *.txt } | cat > outputfile

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.