Linux C中dup2() 与 fcntl() 的区别

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

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
dupdup2是Unix和Linux系统的系统调用函数,用于复制文件描述符。 dup函数的原型为: ```c int dup(int oldfd); ``` dup2函数的原型为: ```c int dup2(int oldfd, int newfd); ``` 这两个函数的作用是将一个已有的文件描述符复制到另一个文件描述符。 - dup函数会返回一个新的文件描述符,该描述符与参数oldfd指向同一文件表项。这意味着对返回的文件描述符的读写操作会影响到原来的文件描述符。 - dup2函数也会返回一个新的文件描述符,但是它可以指定新的文件描述符newfd。如果newfd已经被使用,那么dup2函数会先将newfd关闭,然后再复制oldfd,使得新的文件描述符与oldfd指向同一文件表项。 这两个函数通常用于重定向标准输入、输出和错误流。例如,可以使用dup2函数将标准输出重定向到一个文件: ```c #include <unistd.h> #include <fcntl.h> int main() { int fd = open("output.txt", O_WRONLY | O_CREAT, 0644); if (fd == -1) { perror("open"); return 1; } // 将标准输出重定向到文件 if (dup2(fd, STDOUT_FILENO) == -1) { perror("dup2"); return 1; } // 打印到标准输出,实际上会写入文件 printf("Hello, world!\n"); close(fd); return 0; } ``` 在上面的示例dup2函数将文件描述符fd复制到标准输出描述符STDOUT_FILENO,这样所有的printf函数调用都会将内容写入文件"output.txt"。 希望这个解答能够帮到你!如果还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值