int dup(int oldfd);
int dup2(int oldfd, int newfd);
这两个系统调用都用来创建一个文件描述符(oldfd)的拷贝。
dup()返回一个可用文件描述符中的值最小的文件描述符。
dup2()将文件描述符oldfd拷贝到newfd中,如果newfd是一个正在打开的文件描述符,dup2会先关闭它。以下为例外情况:
* 如果oldfd不是一个有效的文件描述符,dup2返回-1,newfd不会被关闭。
* 如果oldfd是有效的文件描述符,但是和newfd相等,dup2什么也不做,直接返回newfd。
dup2()调用成功后,返回值为newfd。
dup()可以由fcntl实现:
fd = fcntl(oldfd, F_DUPFD, 0);
dup2()有fcntl实现:
close(newfd);
newfd = fcntl(oldfd, F_DUPFD, newfd);
对于dup2的实现存在如下问题:
* 未考虑oldfd的合法性。
* 未考虑oldfd与newfd相等的情况。
* 两条语句之间可能被信号处理程序中断,信号处理程序若调用了open,会导致导致newfd被改写。dup2是原子操作。
例子:
1. 将stderr重定向到stdout:
#include <unistd.h>
...
dup2(STDOUT_FILENO, STDERR_FILENO);
相当于在shell下执行:
myprogram 2>&1
2. 将stdout重定向到文件:
...
int fd;
fd=open("my.out",O_CREAT|O_APPEND|O_RDWR,0644));
...
dup2(fd,STDOUT_FILENO)
close(fd);
...
相当于在shell执行:
myprogram > my.out
stdout重定向到文件的完整的代码:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
int main(){
int fd,ret;
char * filename = "1.tmp";
printf("display in stdout\n");
if ((fd=open(filename,O_CREAT|O_APPEND|O_RDWR,0644)) < 0 ) {
printf("ERROR:fd=%d,errno=%d",fd,errno);
return fd;
}
if ((ret = dup2(fd,STDOUT_FILENO)) < 0) {
printf("ERROR:dup2 error.ret=%d,errno=%d\n",ret,errno);
return ret;
}
printf("display in %s\n",filename);
close(fd);
return 0;
}