dup2() 和 fcntl() 在Linux C中都用于复制文件描述符(表项),但是有一些区别
dup2()
dup2()函数,它是一个系统调用,用于复制一个现有的文件描述符到另一个指定的文件描述符。
dup2函数的原型是int dup2( int oldfd, int newfd);
oldfd:源文件描述符,newfd:目标文件描述符
成功返回目标文件描述符newfd,失败返回-1
dup2函数在复制oldfd 源文件描述符表项时,先会检查由newfd参数所标识的目标文件描述符表项是否空闲,若空闲的话则直接将前者复制给后者。
否则该函数会将newfd 目标文件描述符关闭,然后在将oldfd复制给newfd,并返回新的文件描述符,这意味着newfd将指向和oldfd相同的文件或者资源。
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main(void){
int fd1 = open("dup1.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
if(-1 == fd1){
perror("open");
return -1;
}
printf("fd1 = %d\n", fd1);
int fd2 = open("dup2.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
if(-1 == fd2){
perror("open");
return -1;
}
printf("fd2 = %d\n", fd2);
int fd3 = dup2(fd1, fd2);
if(-1 == fd3){
perror("dup2");
return -1;
}
printf("fd3 = %d\n", fd3);
const char* text = "aaa";
if(-1 == write(fd1, text, strlen(text) * sizeof(text[0]))){
perror("write");
return -1;
}
text = "bbb";
if(-1 == write(fd2, text, strlen(text) * sizeof(text[0]))){
perror("write");
return -1;
}
text = "ccc";
if(-1 == write(fd3, text, strlen(text) * sizeof(text[0]))){
perror("write");
return -1;
}
close(fd3);
close(fd2);
close(fd1);
return 0;
}
运行结果:
liao@liao:~/unixc$ gcc -o dup2 dup2.c
liao@liao:~/unixc$ ./dup2
fd1 = 3
fd2 = 4
fd3 = 4
fcntl()
fcntl()它是一个通用的文件控制函数,可以进行各种文件描述符相关的操作。
fcntl()函数原型:int fcntl( int fd, int cmd,.. ); 只有cmd参数为F_DUPFD时,在某种程度上取代dup2()函数 来复制文件描述符表项
int fcntl( int oldfd, F_DUPFD, int newfd);
成功返回目标文件描述符,失败返回-1
该函数类似于dup2函数 但是不同的是:如果newfd目标文件描述符处于打开open的状态的话,该函数并不会像dup2函数一样先关闭newfd在复制,而是寻找一个比newfd大的最小的空闲的文件描述符作为复制目标。
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main(void){
int fd1 = open("fcntl1.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
if(-1 == fd1){
perror("open");
return -1;
}
printf("fd1 = %d\n", fd1);
int fd2 = open("fcntl2.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
if(-1 == fd2){
perror("open");
return -1;
}
printf("fd2 = %d\n", fd2);
int fd3 = fcntl(fd1, F_DUPFD, fd2);
if(-1 == fd3){
perror("fcntl");
return -1;
}
printf("fd3 = %d\n", fd3);
const char* text = "aaa";
if(-1 == write(fd1, text, strlen(text) * sizeof(text[0]))){
perror("write");
return -1;
}
text = "bbb";
if(-1 == write(fd2, text, strlen(text) * sizeof(text[0]))){
perror("write");
return -1;
}
text = "ccc";
if(-1 == write(fd3, text, strlen(text) * sizeof(text[0]))){
perror("write");
return -1;
}
close(fd3);
close(fd2);
close(fd1);
return 0;
}
运行结果:
liao@liao:~/unixc$ gcc -o fcntl fcntl.c
liao@liao:~/unixc$ ./fcntl
fd1 = 3
fd2 = 4
fd3 = 5