一、dup函数介绍
系统调用dup()创建文件描述符oldfd的一个副本,使用编号最低的未使用描述符作为新描述符。
成功返回后,新旧文件描述符可以互换使用。它们引用相同的打开文件描述,因此共享文件偏移量和文件状态标志;
例如,如果在其中一个描述符上使用lseek(2)修改文件偏移量,则另一个描述符的偏移量也会更改。
这两个描述符不共享文件描述符标志(exec关闭标志)。重复描述符的close on exec标志(FD_CLOEXEC;
请参见fcntl(2))已关闭。
二、头文件和函数定义
#include <unistd.h>
int dup(int oldfd);
代码示例:
#include<stdio.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#define MAX_BUF_LEN 1024
int main()
{
int oldfd = open("tmp.txt", O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
if(oldfd < 0)
{
printf("Open failed!\n");
return -1;
}
int fd2 = dup(oldfd);
if(fd2 < 0 )
{
close(oldfd);
printf("dup() failed!\n");
return -1;
}
char buf[MAX_BUF_LEN];
int bytes;
/* 将标准输入写入buf,这里的0表示的是标准输入描述符,<unistd.h> 定义是 STDIN_FILENO */
while((bytes = read(0, buf, MAX_BUF_LEN - 1)) > 0)
{
if (buf[0] == 'q') {
break;
}
printf("read bytes = %d\n", bytes);
/* 将buf中数据写入fd2,实际写入oldfd */
if(write(fd2, buf, bytes) < bytes)
{
printf("Write failed!\n");
return 0;
}
memset(buf, 0, MAX_BUF_LEN);
}
if (close(fd2) != 0) {
printf("close fd2 error!\n");
}
if (close(oldfd) != 0) {
printf("close oldfd error!\n");
}
return 0;
}
三.dup2函数介绍
dup2()系统调用执行与dup()相同的任务,但它不使用编号最低的未使用文件描述符,而是使用newfd中指定的描述符编号。如果描述符newfd以前是打开的,那么它在被重用之前是静默关闭的。
关闭和重用文件描述符newfd的步骤是以原子方式执行的。这一点很重要,因为尝试使用close(2)和dup()实现等效功能会受到竞争条件的影响,因此newfd可能会在两个步骤之间重用。这种重用可能是因为主程序被分配文件描述符的信号处理程序中断,或者是因为并行线程分配了文件描述符。
注意以下几点:
- 如果oldfd不是有效的文件描述符,则调用失败,newfd未关闭。
- 如果oldfd是有效的文件描述符,并且newfd的值与oldfd相同,那么dup2()不执行任何操作,并返回newfd。
代码示例:
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main()
{
int oldfd;
int fd;
char *buf;
if((oldfd = open("ifconfig.txt", O_RDWR | O_CREAT, 0644)) == -1) {
printf("open error\n");
exit(-1);
}
fd = dup2(oldfd, fileno(stdout));
if(fd == -1)
{
printf("dup2 error\n");
return -1;
}
system("ifconfig");
if (close(oldfd) != 0) {
printf("close oldfd error!\n");
return -1;
}
if (close(fd) != 0) {
printf("close fd error!\n");
return -1;
}
return 0;
}
system函数执行过程中,将标准输出重定向到oldfd中,程序执行完会生成ifconfig.txt文件,内容如下: