如何进行dup和dup2函数的重定向与还原
今天就跟大家聊聊有关如何进行dup和dup2函数的重定向与还原,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
在说重点之前我们先来看看dup 和 dup2 函数的用法
dup 和 dup2 都是系统调用,都可以用来复制文件描述符
#include
int dup(int oldfd);
复制一个老的文件描述符,返回新的文件描述符,且这两个文件描述符共享同一个文件指针,指向同一个文件。
默认文件描述符返回的是没有使用的且最小的。
int dup2(int oldfd, int newfd);
和dup 一样, 只不过自己指定了新的文件描述符。
调用成功,返回新的文件描述符。
shell 中的重定向 " < " (输入) 和 " > "(输出)就是用 dup 函数实现的。
我们来看一段代码。
#include#include #include #include int main(int argc, char *argv[ ]){ int oldfd; oldfd = open("a.txt", O_RDWR | O_CREAT | O_APPEND , 0666); //打开文件 if(old == -1) { printf("creation file failed\n"); exit(-1); } else { dup2(oldfd , 1); // printf("重定向成功\n"); } close(oldfd); return 0;}
运行结果是在a.txt 里面输出" 重定向成功 " 这几个字。
那么现在按照我们自己的理解来分析一下
一个文件描述符对应一个文件指针从而对应一个文件,首先文件描述符 1 对应输出设备(默认为终端),而新创建的
a.txt 返回的文件描述符,我们假定满足一定的条件为 3
所以我们记作:
1 --> 终端
3 --> a.txt
当我们使用dup 以后结果
1 --> a.txt
3 --> a.txt
可以看出 dup 函数说是复制一个文件描述符, 自己理解的花话也可以说成是替换了其中一个文件描述符的指向。1 原本指向终端,现在指向a.txt, 那么原本输出到终端的内容不就输出到a.txt了吗。
这样就完成了" 重定向 "功能。
问题出来了
按照上面的代码,重定向完却并没有恢复,文件指针还是指向代码中的a.txt,我们接着执行程序,输出依然会在a.txt里面,除非你调用exit()或者其他的函数提前结束进程。
那么如果我们想还原呢?
首先我们要定义save_fd 用来保存我们将要覆盖掉的终端的文件描述符
1 --> 终端
3 --> a.txt
4 --> 终端 文件描述符4 为save_fd。
我们已经让一个新的文件描述符指向了终端,那么接下来我们可以放心大胆的改变指向了。
1 --> a.txt
3 --> a.txt
4 --> 终端
在完成重定向以后
加上 dup2(save_fd, 1);
文件描述符 1 的指向变成了 save_fd 的指向,也就是还原到了最开始指向了终端,所以可以继续在终端下输出了。
1 --> 终端
3 --> a.txt
接着我们关闭这个临时" 存储器 "。
close (save_fd);
这样就完成了重定向外加恢复。
然而在实践中我又出现了一些小问题
请看部分代码
oldfd = open("a.txt", O_CREAT | O_APPEND | O_RDWR, 0666); //打开文件
save_fd = dup(1); //保存终端的文件描述符
dup2(oldfd ,1); //重定向到a.txt
printf("重定向成功\n");
dup2(save_fd, 1); //重定向到终端,也就是还原到终端
close(save_fd); //关闭
然而我在输出时," 重定向成功 "这几个字并没有输出到a.txt, 而是依然输出到了屏幕上,
我觉得代码和逻辑都不应该错啊,最后找了一会发现了问题,我用write函数写就能写到 a.txt里面,用printf输出却输出不到 a.txt 里面,最后我在printf()后面加了一个清空缓冲区函数fflush(stdout)就完美的解决了问题,这么说就是缓冲区的问题了,今天的重点也不是缓冲区,而且我也不是那么了解- - 。
我又做了实验,将fflush(stdout)放到了printf()前面,输出结果却依然是不对的。
那么我大胆猜测:
当我们重定向完成后,输出会输出到a.txt也就是指定的文件里,然而printf()函数输出是先到达缓冲区,我们也知道缓冲区是有大小的,所以也要等待缓冲区填满才开始向外" 拿 ",然而在我这个例子中,还没来得及从缓冲区取数据,重定向就复原了,所以依然输出到了屏幕上。这也是我们需要小心谨慎的地方。
补充:dup也可以重定向到网络的socket文件描述符,和管道
看完上述内容,你们对如何进行dup和dup2函数的重定向与还原有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。