让进程等待--waitpid()函数
有些时候,进程之间需要协助才能完成一些任务,比如说,进程A和进程B共同完成一项任务,但是必须进程A先完成,然后进程B再开始,等进程B也完成了,任务也就完成了。
先给出一个有问题的实例,然后我们来分析并解决它:
aa.c
//父进程
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
int main(){ pid_t pid = fork(); if(pid == -1){ fprintf(stderr,"%s:%s\n","Can't fork process",strerror(errno)); exit(1); } if(!pid){ execl("bb","bb",NULL); } FILE *my_file = fopen("test.log","r"); char c[80]; fscanf(my_file,"%79[^\n]\n",c); printf("%s\n",c); return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
bb.c
//子进程 #include <stdio.h> #include <unistd.h> int main(){ FILE *my_file = fopen("test.log","w"); if(my_file == NULL){ fprintf(stderr,"error!!!!"); } sleep(5); fprintf(my_file,"Hello world!Good morning!"); fclose(my_file); return 0; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
编译运行:
~/Desktop/MyC$ touch test.log
~/Desktop/MyC$ gcc aa.c -o aa
~/Desktop/MyC$ gcc bb.c -o bb
~/Desktop/MyC$ ./aa
|
~/Desktop/MyC$ tail -f test.log
Hello world!Good morning!
- 1
- 2
- 3
- 4
- 5
- 6
- 7
原因分析:
首先说说这个程序要达到的目的,首先父进程aa打开子进程bb,子进程负责把“Hello world!Good morning!”写入文件test.log。然后父进程aa再把test.log内容读出来。但是这个有问题的实例,在运行后,并没有打印任何内容。使用tail命令查看test.log文件时,发现数据已成功写入。
为什么会这样呢?
其实是因为创建的子进程与父进程之间已没有任何关系了。也就是说父进程并没有等待子进程执行完,就自己执行完了。有没有办法让父进程等待子进程执行完毕再继续执行呢?答案是有的,使用waitpid()函数。
waitpid()函数会等待子进程结束以后才返回。因此我们调整一下主程序aa.c的代码:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
int main(){ pid_t pid = fork(); if(pid == -1){ fprintf(stderr,"%s:%s\n","Can't fork process",strerror(errno)); exit(1); } if(!pid){ execl("bb","bb",NULL); } int pid_status; if(waitpid(pid,&pid_status,0) == -1){ fprintf(stderr,"error !!!"); return 2; } FILE *my_file = fopen("test.log","r"); char c[80]; fscanf(my_file,"%79[^\n]\n",c); printf("%s\n",c); return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
我们在主程序中添加了
if(waitpid(pid,&pid_status,0) == -1){ fprintf(stderr,"error !!!"); return 2; }
- 1
- 2
- 3
- 4
这段代码的意思就是要等待子程序执行完毕。
编译运行一下:
~/Desktop/MyC$ gcc aa.c -o aa
~/Desktop/MyC$ ./aa
Hello world!Good morning!
- 1
- 2
- 3
结果符合我们的预期。
分析一下waitpid(pid,pid_status,options)函数:
pid:父进程克隆子进程时会得到子进程的ID。更多进程信息尽在进程与系统调用——fork、exec
pid_status: 用来保存进程的退出信息。因为waitpid()需要修改pid_status,因此它必须是个指针。
options:可以通过man waitpid查看它的选项,如果把选项设为0,函数将等待进程结束。
什么是pid_status?
waitpid()函数结束等待时会在pid_status中保存一个值,它告诉你进程的完成情况。为了得到子进程的退出状态,可以把pid_status的值传给WEXITSTATUS()宏:
if(WEXITSTATUS(pid_status)){ //如果退出状态不是0
puts("Error status non-zero");
}
- 1
- 2
- 3
谢谢阅读!
文章来源: blog.csdn.net,作者:WongKyunban,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/weixin_40763897/article/details/87612900
- 点赞
- 收藏
- 关注作者
评论(0)