<p><pre><code> > the file entry data structure maintains a file offset for
> every process
</code></pre>
File table entries aren't per-process. That's dangerously misleading. Without getting lost in the weeds, just remember that new file table entries are usually created for every open() or socket() call, in addition to a new descriptor table entry. Contrast that with dup() or fork(), which create new descriptor table entries that point to shared file table entries.<p>Why would this matter? Because as the article suggests (albeit ambiguously), a fork() has semantics similar to dup() in that the new process gets a cloned descriptor table. <i>but</i> with pointers to _shared_ file table entries. Why this matters, and why the article is misleading, is because when two processes perform reads through a shared file table entry for a regular file, the order of reads will matter as between the two processes because of the shared cursor; the sequence of data each process reads could differ based on random scheduling latencies.<p>File position cursors really only matter for regular files, not pipes or sockets. But another thing to keep in mind is the distinction between descriptor flags and file entry flags[1]. O_CLOEXEC is a descriptor flag, which means it's not inherited when you dup() a descriptor (it is inherited across a fork, but that's because you're getting a clone of the entry which is thereafter distinct). However, flags like O_NONBLOCK are file entry flags, which means if process A forks process B and process B does fcntl(fd4, F_SETFL, O_NONBLOCK), all of a sudden fd4 will behave in a non-blocking manner in process A. Likewise, if you do dup2(fd4, fd5) then fcntl(fd5, F_SETFL, O_NONBLOCK), all of a sudden fd4 is non-blocking.<p>One interesting distinction between BSD and Linux is that on BSD opening /dev/fd/N is identical to calling dup(); even though you're using open() you get a shared file table entry. However, Linux symlinks /dev/fd to /proc/self/fd and you get regular open() semantics with an unshared file table entry.<p>On Linux, at least, you can create a new file table entry for an existing pipe through /proc/self/fd. But AFAIK you can't open sockets through /proc/self/fd. I've never really run into the need to do this, though. But it's good to keep all of this in mind for regular files because shared cursors could easily cause headaches, perhaps even security issues.<p>FWIW, Unix descriptor passing has dup() semantics.<p>[1] Technically the term is file status flags, but when discussing this I prefer file entry flags (or file table entry flags) to highlight the relationship to descriptor flags.