dup2 / dup - why would I need to duplicate a file descriptor?

南笙酒味 提交于 2019-11-27 17:06:06

The dup system call duplicates an existing file descriptor, returning a new one that refers to the same underlying I/O object.

Dup allows shells to implement commands like this:

ls existing-file non-existing-file > tmp1  2>&1

The 2>&1 tells the shell to give the command a file descriptor 2 that is a duplicate of descriptor 1. (i.e stderr & stdout point to same fd).
Now the error message for calling ls on non-existing file and the correct output of ls on existing file show up in tmp1 file.

The following example code runs the program wc with standard input connected to the read end of a pipe.

int p[2];
char *argv[2];
argv[0] = "wc";
argv[1] = 0;
pipe(p);
if(fork() == 0) {
    close(STDIN); //CHILD CLOSING stdin
    dup(p[STDIN]); // copies the fd of read end of pipe into its fd i.e 0 (STDIN)
    close(p[STDIN]);
    close(p[STDOUT]);
    exec("/bin/wc", argv);
} else {
    write(p[STDOUT], "hello world\n", 12);
    close(p[STDIN]);
    close(p[STDOUT]);
}

The child dups the read end onto file descriptor 0, closes the file de scriptors in p, and execs wc. When wc reads from its standard input, it reads from the pipe.
This is how pipes are implemented using dup, well that one use of dup now you use pipe to build something else, that's the beauty of system calls,you build one thing after another using tools which are already there , these tool were inturn built using something else so on .. At the end system calls are the most basic tools you get in kernel

Cheers :)

Another reason for duplicating a file descriptor is using it with fdopen. fclose closes the file descriptor that was passed to fdopen, so if you don't want the original file descriptor to be closed, you have to duplicate it with dup first.

Some points related to dup/dup2 can be noted please

dup/dup2 - Technically the purpose is to share one File table Entry inside a single process by different handles. ( If we are forking the descriptor is duplicated by default in the child process and the file table entry is also shared).

That means we can have more than one file descriptor having possibly different attributes for one single open file table entry using dup/dup2 function.

(Though seems currently only FD_CLOEXEC flag is the only attribute for a file descriptor).

http://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html

dup(fd) is equivalent to fcntl(fd, F_DUPFD, 0);

dup2(fildes, fildes2); is equivalent to 

   close(fildes2);
   fcntl(fildes, F_DUPFD, fildes2);

Differences are (for the last)- Apart from some errno value beteen dup2 and fcntl close followed by fcntl may raise race conditions since two function calls are involved.

Details can be checked from http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html

An Example of use -

One interesting example while implementing job control in a shell, where the use of dup/dup2 can be seen ..in the link below

http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs

dup is used to be able to redirect the output from a process.

For example, if you want to save the output from a process, you duplicate the output (fd=1), you redirect the duplicated fd to a file, then fork and execute the process, and when the process finishes, you redirect again the saved fd to output.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!