让进程等待--waitpid()函数

举报
yd_221104950 发表于 2020/12/02 22:45:38 2020/12/02
【摘要】 有些时候,进程之间需要协助才能完成一些任务,比如说,进程A和进程B共同完成一项任务,但是必须进程A先完成,然后进程B再开始,等进程B也完成了,任务也就完成了。 先给出一个有问题的实例,然后我们来分析并解决它: aa.c //父进程 #include <stdio.h> #include <unistd.h> #include <string.h> #include <...

有些时候,进程之间需要协助才能完成一些任务,比如说,进程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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。