dup() 和 dup2() 都可以用来复制一个现有的文件描述符,这两个函数声明如下:
[C++] 纯文本查看 复制代码
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
dup() 函数返回的新文件描述符一定是当前可用文件描述符中的最小值。
dup2() 函数可以将第 1 个参数 oldfd 指定的文件描述符复制到第 2 个参数 newfd 中,newfd 是由用户指定的一个整数,并不一定是可用文件描述符中最小的那个。需要注意的是:
1. 如果 newfd 已经打开,那么会先将其关闭。
2. 如果 oldfd 是个无效的文件描述符,则调用失败,而且 newfd 在已经打开的情形下也不会被关闭。
3. 如果 oldfd 有效,且等同于 newfd ,那么函数什么都不做,直接返回 newfd 。
在函数成功返回后,老的和新的文件描述符可以互换使用,它们共享同一个文件表项(文件偏移,文件状态标志等)。例如,如果使用 lseek() 函数在一个描述符上修改了文件偏移,那么对于另外一个描述符来说这个偏移也是同样被修改了的。
每个文件描述符都有它自己的一套文件描述符标志(注意,不是文件表项;比如 close-on-exec 文件描述符标志 FD_CLOEXEC)。
另外,复制一个描述符的另一种方法是通过 fcntl() 函数,比如 dup2(oldfd, newfd) 等同于 close(newfd); fcntl (oldfd, F_DUPFD, newfd);
测试代码:
[C++] 纯文本查看 复制代码
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
print_line(int n)
{
char buf[32];
const char *ptr = "hello";
snprintf(buf, sizeof(buf), "Line #%d\n", n);
write(1, buf, strlen(buf));
}
int main()
{
int fd;
print_line(1);
print_line(2);
print_line(3);
/*重定向标准输出 stdout 到文件 dup.out 中*/
fd = open("dup.out", O_WRONLY|O_CREAT,0666);
assert(fd>=0);
printf("fd=%d\n", fd);
dup2(fd, 1);
print_line(4);
print_line(5);
print_line(6);
close(fd);
close(1);
return 0;
}
程序运行以及输出结果:beyes@linux-beyes:~/C/call> ./dup.exe
Line #1
Line #2
Line #3
fd=3
beyes@linux-beyes:~/C/call> cat dup.out
Line #4
Line #5
Line #6 说明:
在 print_line() 函数中,snprintf() 把格式好的字符串复制到 buf 指向的空间中;然后用 write 把 buf 缓冲区中的数据写到标准输出。
27行:经过 dup2() 函数后,标准输出就成为了 fd 的一个副本,也就是说,操作标准输出描述符 1 也就相当于操作到了 fd 上( 新旧文件描述符指向同一个文件,共享所有的锁定、读写指针和各项权限或标志位)。效果如像上面所示,标准输出被的重定向到文件中去了。
|