BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #101681同步于 2022/2/12
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

【问题】关于子进程与文件描述符的小问题

yoelee
2022/2/12镜像同步10 回复
#### 关于子进程与文件描述符的小问题 ##### 现象描述: 我在main函数中打开了一个文件输入流,在while循环中逐行将文件中的内容打印出来。在while循环的打印语句之后fork一下,fork后的子进程直接exit,父进程则继续循环打印。然鹅编译运行这段代码,发现程序会将文件里面的内容**循环打印无数遍**。在子进程调用exit前增加一句fclose fp可以解决这个问题。 ##### 问题: 为什么在增加语句fclose fp之前,程序会**重复打印**文件的内容?是子进程的exit操作改变了什么吗?在网上没有找到解答,球球各位大佬伸伸援手 `代码`如下 ```c #include<stdio.h> #include<unistd.h> #include<sys/wait.h> #include<stdlib.h> int main(){ FILE* fp = fopen("./hello.txt","r");//打开文件流 char*str=NULL; size_t size = 0; while(getline(&str,&size,fp)!=-1){//在fp打开的文件中读取一行内容到str中 printf("%s",str);//打印str //fork之后子进程exit,父进程继续打印 pid_t child = fork(); if(child==0){ //fclose(fp);//如果子进程关闭它的fp,问题就可以得到解决 exit(0); } else if(child >0) { wait(NULL); continue; } } return 0; } ``` 下面是`./hello.txt`的内容 ```c a b chard elsed fopen ``` 图片: 添加fclose语句之前,文件内容被重复打印: 添加fclose语句之后的结果:
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
yoelee机器人#1 · 2022/2/12
自顶自顶
RinChanNOW机器人#2 · 2022/2/12
出现这个的原因是fork出来的进程与父进程共享文件表项,也共享文件的读取偏移量,但是当子进程 exit() 的时候,会帮你关闭这个文件(fclose),然后关闭这个文件的时候可能会将这个文件的偏移量回退,导致另一个进程读取进度也回退了,造成了这种死循环。解决办法是将调用的 exit() 替换为 _exit(),直接退出进程而不进行其他处理。参考:https://stackoverflow.com/a/54915495。具体细节可以看看这个答案里给出的链接。
RinChanNOW机器人#3 · 2022/2/12
另外,在我的wsl(Ubuntu 20.04)上,删掉你hello.txt的最后一行可以正常退出(不会死循环),不过仍然会重复读取数据。你直接fclose也有问题,会读取最后一行两次。
yoelee机器人#4 · 2022/2/12
收到!谢谢大哥,我搞了一下午都没搞明白 【 在 RinChanNOW 的大作中提到: 】 : 出现这个的原因是fork出来的进程与父进程共享文件表项,也共享文件的读取偏移量,但是当子进程 exit() 的时候,会帮你关闭这个文件(fclose),然后关闭这个文件的时候可能会将这个文件的偏移量回退,导致另一个进程读取进度也回退了,造成了这种死循环。解决办法是将调用的 exit() 替换为 _exit(),直接退出进程而不进行其他处理。参考:https://stackoverflow.com/a/54915495。具体细节可以看看这个答案里给出的链接。 : --
RinChanNOW机器人#5 · 2022/2/13
我也是昨天看到你这个问题才去了解的,共同学习共同进步[ema21] 【 在 yoelee 的大作中提到: 】 : 收到!谢谢大哥,我搞了一下午都没搞明白
hueru机器人#6 · 2022/3/3
请问一下,既然偏移量回退了,为啥不是一直输出第一行数据呢? 【 在 RinChanNOW 的大作中提到: 】 : 我也是昨天看到你这个问题才去了解的,共同学习共同进步[ema21]
RinChanNOW机器人#7 · 2022/3/3
因为相当于重新从头开始读了,就变成和一开始一样了,造成了循环 【 在 hueru 的大作中提到: 】 : 请问一下,既然偏移量回退了,为啥不是一直输出第一行数据呢?
hueru机器人#8 · 2022/3/4
是啊,那应该一直循环读第一行啊 【 在 RinChanNOW 的大作中提到: 】 : 因为相当于重新从头开始读了,就变成和一开始一样了,造成了循环
RinChanNOW机器人#9 · 2022/3/4
我上面说的有问题,回退不是会退到开头,具体我也不知道是回退多少,可以看看那个stackoverflow的回答。看他的描述应该是由于有两个进程都在读同一个文件,当一个进程读到EOF的时候,为了保证另一个进程也能正常读,需要回退到读之前的位置,不知道是不是这个意思。 【 在 hueru 的大作中提到: 】 : 是啊,那应该一直循环读第一行啊