使用dup2后如何将stdin恢复为原始标准输入?fork方案是否可行?
问题解答
1. stdin恢复到原始指向的实现方案
有两种成熟的实现方式可以满足需求:
- 方案1:提前备份原始stdin。在调用
dup2修改stdin指向之前,先调用dup(STDIN_FILENO)复制原始stdin的文件描述符并存为临时变量,需要恢复时再调用dup2(备份fd, STDIN_FILENO)即可,恢复完成后关闭备份的fd释放资源即可。
参考代码示例:
#include <unistd.h> #include <fcntl.h> #include <stdio.h> int main() { // 备份原始stdin int stdin_bak = dup(STDIN_FILENO); if (stdin_bak == -1) { perror("备份stdin失败"); return 1; } // 把stdin重定向到test.txt int fd = open("test.txt", O_RDONLY); if (fd != -1) { dup2(fd, STDIN_FILENO); close(fd); } // 此处运行需要重定向stdin的业务逻辑 char buf[1024]; fgets(buf, sizeof(buf), stdin); printf("重定向后读取内容:%s\n", buf); // 恢复原始stdin dup2(stdin_bak, STDIN_FILENO); close(stdin_bak); return 0; }
- 方案2:你提到的fork方案完全可行。子进程处理完逻辑退出后,父进程的stdin完全不受影响,不需要额外做恢复操作,适合不需要在父进程复用重定向结果的场景。
2. 父子进程文件描述符的共享规则
父子进程的文件描述符不是实时共享的:
fork执行时,内核会给子进程创建独立的文件描述符表,拷贝父进程当前所有文件描述符的值,后续父子进程各自对自己的文件描述符做修改(比如dup2重定向、close关闭操作)都只会作用于自身的描述符表,不会互相影响。
唯一的共享点是:父子进程相同fd对应的底层文件对象(比如文件偏移量、文件状态标记)是共享的,比如父进程读取文件后偏移量跳到100,子进程读取同一个fd时会直接从偏移100的位置开始读,但如果子进程把这个fd重定向到其他文件,父进程的fd依然指向原来的文件,互不干扰。
内容的提问来源于stack exchange,提问作者blue
相关产品推荐
相关产品推荐

