0

I'm trying to create a linux daemon in c and found some sample code on this page.

I understand all the code except where it tries to redirect STDIN, STDOUT and STDERR (to /dev/null/). I also found a number of questions on here related to why these should be redirected (which I understand).

Specifically the section of code my question relates to is:

/* Route I/O connections */

/* Open STDIN */
i = open("/dev/null", O_RDWR);

/* STDOUT */
dup(i);

/* STDERR */
dup(i);

Reading the man page for dup() it implies that dup() simply duplicates a file descriptor.

So I don't understand how this does the redirect ? Is the compiler taking hints from the comments in the line above ?, or is it missing some code ?, is it plain wrong ?, or am I missing something ?

KennetRunner
  • 287
  • 1
  • 12
  • 2
    Did that example close the existing STDIN, STDOUT and STDERR before creating new ones? So that the next free fd to use would be 0, then 1, then 2 – infixed Dec 02 '16 at 16:26
  • 1
    Possible duplicate of [Redirecting STDIN, STDOUT, STDERR to /dev/null in C](http://stackoverflow.com/questions/4263173/redirecting-stdin-stdout-stderr-to-dev-null-in-c) – Jean-François Fabre Dec 02 '16 at 16:26

2 Answers2

1

From the man page of dup:

The dup(oldfd) system call creates a copy of the file descriptor oldfd, using the lowest-numbered unused descriptor for the new descriptor.

If you see the referenced code, he is first closing all the open file descriptors:

      for (i = getdtablesize(); i >= 0; --i)
         {
            close(i);
         }

After that when you call dup(i), it will copy the file descriptor i to the lowest available descriptor, which will be 0 (stdin). Doing that again will copy it to descriptor 1 (stdout) and similarly for descriptor 2 (stderr). In this way, the stdin, stdout, and stderr of the daemon process are pointing to /dev/null.

Every process gets three open file descriptors which are the stdin, stdout, and stderr (these descriptors usually have the values 0, 1, and 2 respectively). When you call printf(), for example, it writes to the file pointed to by the stdout descriptor. By pointing this descriptor to another file (such as /dev/null), any output from this process will get redirected to that file. Same logic applies for stdin and stderr.

On the shell, when you run something like ls > ls.out, the shell does the same. It fork()s a new process, opens ls.out for writing, and calls dup (or dup2) to copy the file descriptor of ls.out to this process' stdout.

Abhinav Upadhyay
  • 2,477
  • 20
  • 32
1

It's import to understand the previous bit of the example code you link to:

/* close all descriptors */
        for (i = getdtablesize(); i >= 0; --i)
        {
            close(i);
        }

This closes all open file descriptors including STDIN, STDOUT and STDERR.

As the manpage for open() states

The file descriptor returned by a successful call will be the lowest-numbered file descriptor not currently open for the process

So the subsequent call to open() in the example code will redirect file descriptor 0 which is STDIN, to /dev/null.

The subsequent calls to dup() will duplicate the file descriptor using the next lowest numbers. STDOUT is 1, and STDERR is 2.

The manpage for dup() states:

The dup() system call creates a copy of the file descriptor oldfd, using the lowest-numbered unused descriptor for the new descriptor

NickBroon
  • 367
  • 3
  • 13