dup (system call)
In Unix-like operating systems, dup and dup2 system calls create a copy of a given file descriptor. This new descriptor actually does not behave like a copy, but like an alias of the old one.
C library POSIX definition
These dup and dup2 calls are standardized by the POSIX specification
int dup (int oldfd);
int dup2 (int oldfd, int newfd);
The former allocates the first available descriptor, just like open() behaves; an alternative way to duplicate a file descriptor to an unspecified place is the fcntl system call with F_DUPFD
command.
The latter places a copy to a specified location (index), closing a file descriptor if it already exists.
Importance of dup2 for Unix shells
Unix shells use dup2 for input/output redirection. Along with pipe()
, it is a tool on which Unix pipes rely.
The following example uses pipe()
and dup()
in order to connect two separate processes (program1 and program2) using Unix pipes:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/* function prototypes */
void die(const char*);
int main(int argc, char **argv) {
int pdes[2];
pid_t child;
if(pipe(pdes) == -1)
die("pipe()");
child = fork();
if(child == (pid_t)(-1))
die("fork()"); /* fork failed */
if(child == (pid_t)0) {
/* child process */
close(1); /* close stdout */
if(dup(pdes[1]) == -1)
die("dup()");
/* now stdout and pdes[1] are equivalent (dup returns lowest free descriptor) */
if((execlp("program1", "program1", "arg1", NULL)) == -1)
die("execlp()");
_exit(EXIT_SUCCESS);
} else {
/* parent process */
close(0); /* close stdin */
if(dup(pdes[0]) == -1)
die("dup()");
/* now stdin and pdes[0] are equivalent (dup returns lowest free descriptor) */
if((execlp("program2", "program2", "arg1", NULL)) == -1)
die("execlp()");
exit(EXIT_SUCCESS);
}
return 0;
}
void die(const char *msg) {
perror(msg);
exit(EXIT_FAILURE);
}
Use in Perl language
Perl does not provide these system calls directly. But dup2
to redefine one of standard streams may be invoked via "pipe opens" technique, using the vertical bar character in the file path for the open()
call. Namely,
open FILE, "| shell command"
performs pipe()
, fork()
, dup2(…,STDIN) and then executes a specified command.
Likewise,
open FILE, "shell command |"
performs pipe()
, fork()
, dup2(…,STDOUT) and then executes a specified command.
See also
- File descriptor – how it works and other functions related to open
References
- Advanced Programming in the UNIX Environment by W. Richard Stevens ISBN 81-7808-096-6