36

Say I have process 1 and process 2. Both have a file descriptor corresponding to the integer 4.

In each process however the file descriptor 4 points to a totally different file in the Open File Table of the kernel:

enter image description here

How is that possible? Isn't a file descriptor supposed to be the index to a record in the Open File Table?

Pithikos
  • 3,294
  • 2
    Good question! My guess is that the file descriptors are translated, so that the fd 4 in both processes are relative to it's own number of open fd's. Fd's 0-2 (stdin,stdout,sdterr) are always opened for a new process and the numbers are not reserved for only that process. –  Jan 05 '12 at 16:04
  • 1
  • @jw013 I thought this sounded familiar. @Pithikos How is this not a duplicate? – Michael Mrozek Jan 05 '12 at 16:23
  • @Michael Mrozek This is indeed a duplicate. However I reedited the question as I didn't get any good explanation on the old one. (This scheme is also much more relevant to the question.) – Pithikos Jan 05 '12 at 16:33
  • @Pithikos Ok; I'm going to merge that one into this one then. In the future, this is what bounties are for – Michael Mrozek Jan 05 '12 at 16:36
  • 2
    This is a poor diagram - it should show that file descriptor 4 means the fourth entry [well, fifth, it's counted from zero] of the file descriptor table on the left, not an entry which contains a "4". The actual "4" lives in your userspace variable containing the number. The diagram in the other question is much better. – Random832 Jan 05 '12 at 18:21
  • 2
    @Random832 Well if I knew which diagram was correct then I would probably never had made this question. – Pithikos Sep 17 '14 at 17:13
  • If I fork a process and then if I want to redirect the stdout file descriptor of the child, from parent how can I achieve this? – ivcode Dec 17 '15 at 10:18

5 Answers5

47

The file descriptor, i.e. the 4 in your example, is the index into the process-specific file descriptor table, not the open file table. The file descriptor entry itself contains an index to an entry in the kernel's global open file table, as well as file descriptor flags.

jw013
  • 51,212
  • 3
    For the record, there is only one "file descriptor flag" on most systems, the close-on-exec flag. All other "per-fd" state (including the offset and the access mode) is part of the open file table entry. – Random832 Jan 05 '12 at 18:45
31

Each process has its own file descriptor table. File descriptor 4 in process 1234 points inside process 1234's table. File descriptor 4 in process 5678 points inside process 5678's table. A case you must be familiar with are file descriptors 0, 1 and 2 which for each process are the standard input, standard output and standard error, pointing wherever these were redirected to.

A process can open the same file more than once. This can happen coincidentally, for example when a process's standard output and standard error are redirected to the same terminal or to the same file. The underlying file table entries (e.g. Linux's struct file) carry more than information about the file; they also contain opening modes (e.g. read or write) and other state (such as flags, e.g. close-on-exec). For example, a process might have a terminal opened for reading only on file descriptor 0 and that same terminal opened for writing only on file descriptor 2. File tables entries also contain the process's position in the file; a process might want to lseek to two different positions in the same file, and so would use dup to obtain two handles to that file.

  • 3
    This isn't entirely correct. According to the man page / specs, dup does an exactly what it says on the tin: both resulting descriptors point to the same file table entry and thus share the same offset. In order to get 2 different file table entries, I'm pretty sure you need to open the file twice. – jw013 Dec 17 '11 at 01:32
  • @Gilles "File descriptor 4 in process 1234 points inside process 1234's table". Which table do you mean? From what I know the only table in the process is the File Descriptor Table where each record points to the kernel's single Open File Table. – Pithikos Jan 05 '12 at 15:35
  • 1
    See http://unix.stackexchange.com/questions/195057/what-is-an-open-file-description/195164#195164 for a more precise description. – Gilles 'SO- stop being evil' Apr 08 '15 at 23:56
9

Each process has it's own file descriptor table. That's all.

It's all very well described in UNIX Network Programming by Richard Stevens if you would like to learn it deeply.

8

Wouldn't an extra level of indirection fix your problem? ("All problems in computer programming can be solved by an extra level of indirection" - some wise greybeard). That is, the small integer in each process ends up as an index into a per-process array of kernel-space indexes into the "Open File Table".

  • 3
    The source wise greybeard is likely David Wheeler. It appears he also said, "But that usually will create another problem." :) – jw013 Jan 05 '12 at 16:12
0

For getting an intuition on why every file descriptor should be indexed on local file descriptor table, one can see the case of redirection in unix systems. For a process one can redirect its stdout to any other file and thus overloading the file descriptor "1" for that process without altering what that "1" meant for other process. Same holds true for stdin and stderr. Thus there must be a local file descriptor to support such behaviour.

lastbreath
  • 101
  • 1