21

This is actually a two-step question:

  1. What exactly is a file descriptor? I thought it was the most fundamental way to represent an open file. But since dup2 can make two different file descriptors point to the same file, then what is it that represents a unique file?

  2. If I do dup2 before exec, the whole program is then wiped out, does it still have the same file descriptor table? Do the redirected file descriptors still are redirected?

Xufeng
  • 6,452
  • 8
  • 24
  • 30

1 Answers1

29

Yes. Open file descriptors are preserved across a call to exec. From the execve man page (all exec* calls are just a wrapper around this system call):

By default, file descriptors remain open across an execve(). File descriptors that are marked close-on-exec are closed; see the description of FD_CLOEXEC in fcntl(2).

  1. Yes, a file descriptor is the way that userspace refers to open files when making system calls. (Or socket, or pipe, etc.) The fact that they can be duplicated doesn't change that. They are simply multiple references to the same open file. See also:

  2. Yes, as mentioned in the man page quote.

In fact, many programs (including your shell) rely upon this feature. If it wasn't so, your program would start up without the standard in/out/error file descriptors open! When the shell runs a program, it forks, dup2's the open tty file descriptors to 0,1,2, and then execve's your new program.

Community
  • 1
  • 1
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • 2
    +1: Also, when you `fork()`, every descriptor is copied, and the file descriptors in the child point to the same open file description as the corresponding file descriptors in the parent. And `dup()` and `dup2()` give you another reference to the same open file description. See the [`open()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html) manual page for POSIX (and related pages). – Jonathan Leffler Mar 07 '14 at 04:00
  • @Jonathon "when the shell runs a program, it `fork`s and `dup`s the open tty(?) file descriptors to 0, 1, 2 and then `execve`s your new program". Can I get a reference for further reading. – Sourav Kannantha B Mar 08 '22 at 20:57
  • @SouravKannanthaB Consult the source code for your favorite [Unix shell](https://en.wikipedia.org/wiki/Unix_shell) ([`sh`](https://en.wikipedia.org/wiki/Bourne_shell), [`ksh`](https://en.wikipedia.org/wiki/KornShell), [`csh`](https://en.wikipedia.org/wiki/C_shell), [`bash`](https://en.wikipedia.org/wiki/Bash_(Unix_shell)), [`zsh`](https://en.wikipedia.org/wiki/Z_shell), [`ash`](https://en.wikipedia.org/wiki/Almquist_shell), etc.) – Jonathon Reinhart Mar 08 '22 at 22:09
  • @JonathonReinhart it'd probably be much more useful to link to the source instead of the wikipedia pages... – somebody Oct 24 '22 at 08:26
  • @somebody There is plenty of comment space. Please feel free to add the links yourself! – Jonathon Reinhart Oct 27 '22 at 03:25
  • [`ksh`](https://github.com/ksh2020/ksh/blob/8cf92b281a8d5da075b28e4421ec7ec0ab0de1ce/src/cmd/ksh93/sh/xec.c#L909), [`bash`](https://github.com/bminor/bash/blob/a99d905216cc0aac5de0c3050f4afc54e21c6bc5/execute_cmd.c#L2495), [`dash`](https://git.kernel.org/pub/scm/utils/dash/dash.git/tree/src/eval.c?id=6f6d1f2da03468c0e131fdcbdcfa9771ffca2614#n893)... too tired to do the other ones right now – somebody Oct 27 '22 at 11:39