dup和dup2

阅读一些C或者C++第三方库开源源码的时候,有些源码中会使用dup和dup2这两个函数,由于在工作中基本上用不到这两个函数,所以它们对阅读源代码提升了一些难度。虽然当时看过相关博文后能理解,不过过了一段时间就又忘了,今天不算总结,就把这两个函数的经典特性给blog出来。

先看一下dup和dup2函数的原型:

#include<unistd.h>
int dup(int fd);
int dup2(int fd1,int fd2);
两个均为复制一个现存的文件的描述
两个函数的返回:若成功为新的文件描述,若出错为-1;
由dup返回的新文件描述符一定是当前可用文件描述中的最小数值。
用dup2则可以用fd2参数指定新的描述符数值。
如果fd2已经打开,则先关闭。若fd1=fd2,则dup2返回fd2,而不关闭它。
通常使用这两个系统调用来重定向一个打开的文件描述符。

我看完这一段话之后,感觉非常抽象,还是用一个例子说明吧。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char** argv)
{
	int fd = open("./test.conf", O_RDWR | O_CREAT);
	printf("fd: %d\n", fd);
	close(1);
	dup(fd);
	printf("ma52103231\n");
}
从这段代码中可以看到,先用open打开文件。为什么是open而不是fopen?因为dup和dup2的参数是文件描述符而不是fopen返回的FILE*指针。

然后使用printf打印出fd的值。接着使用close关闭文件描述符1(1当前指代这标准输出),关闭的意思就是解绑,把1和标准输出解除绑定,之后对1的操作再也影响不到标准输出了,而1处于空闲状态。在之后使用dup(fd)来duplicate参数fd。这在系统内部执行了一个查询操作。内部会寻找当前可用的最小空闲文件描述符,由于1已经处于空闲状态,所以1也指向了fd指向的test.conf文件,而test.conf文件的引用计数加一。最后使用printf输出语句,由于printf默认将语句输出到文件描述符1,所以看如下内容:

root@hu-virtual-machine:/home/hu/project/c_# gcc main.c -o myexpect
root@hu-virtual-machine:/home/hu/project/c_# ./myexpect 
fd: 3
root@hu-virtual-machine:/home/hu/project/c_# cat test.conf 
ma52103231
root@hu-virtual-machine:/home/hu/project/c_# 
从上可以看到,“ma52103231”被printf写入到了文件中。同时注意到fd的值为3,说明,一个程序在运行时,文件描述符0,1,2默认已经打开,这个时候空闲的最小文件描述符是3.

再来看dup2,依然通过一个例子:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char** argv)
{
	int fd = open("./test.conf", O_RDWR | O_CREAT);
	printf("fd: %d\n", fd);
	close(1);
	dup(fd);

	dup2(fd, 2);
	fprintf(stdout, "ma52103231\n");
	fprintf(stderr, "this is a error\n");
	
}
我们知道文件描述符2指代标准错误,通过dup2函数,将fd duplicate到文件描述符2,不过在此之前,先close调文件描述符2,所以代码中没有出现close(2这个语句),因为dup2函数已经帮我们做了这一步。程序最后通过fprintf函数将内容写到第一个参数指定的目标中去的特性,实现写文件,看一下文件内容:
root@hu-virtual-machine:/home/hu/project/c_# cat test.conf 
ma52103231
this is a error

以上就是dup和dup2两个函数的使用小例子。再使用两个函数的过程中,要清楚的明白,它们在执行时会执行一个寻找操作,寻找当前程序中 最小的处于 空闲状态的文件描述符,而一般来说close函数会使一个描述符变成空闲(假若一个描述符的引用计数很多,调用一次close并不会使这个描述符空闲,所以是一般来说,不过在使用dup和dup2的场景中,这样的情况我是很少看到),所以dup和close经常成对出现。而对于dup2,一定要记住,它内部有个close操作。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值