wait()函数说明

wait(等待子进程中断或结束,相关函数 waitpid,fork)

表头文件

#include#include

函数原型

pid_t wait (int * status);

函数说明

参数 status 是一个整形指针。如果status不是一个空指针,则终止进程的终止状态将存储在该指针所指向的内存单元中。如果不关心终止状态,可以将 status参数设置为NULL。

status 不是NULL时子进程的结束状态值会由参数 status 返回,而子进程的进程识别码作为函数返回值返回。

调用 wait 函数时,调用进程将会出现下面的情况:

如果其所有子进程都还在运行,则阻塞。

如果一个子进程已经终止,正等待父进程获取其终止状态,则获取该子进程的终止状态然后立即返回。

如果没有任何子进程,则立即出错返回。

(图源网络,侵删)

返回值

如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。

//fork()的使用方法,如果不进行wait()则当子进程退出时会出现子进程的内存无法释放的状态,因此子进程便成为了僵尸进程。

#include

#include

#include

int main(){

pid_t pid;

printf("Start of fork testing\n");

pid = fork();

printf("Return of fork success:pid = %d\n",pid);

printf("father :%d %d",getpid(),getppid());

return 0;

}

//当没有子进程的时候,调用wait()的返回值是-1

#include

#include

#include

#include

int main(){

printf("wait return :%d",wait(NULL));

return 0;

}

运行结果:

wait return :-1

//一个wait(NULL)只能等待一个子进程结束,两个等待两个子进程

#include

#include

#include

#include

int main(){

int pid;

printf("father progress,and father progress pid is %d\n",getpid());

if(0 == fork()){

printf("father progress forked,and child progress pid is %d\n",getpid());

}

else{

if(0 == fork()){

printf("father progress forked,and child progress pid is %d\n",getpid());

}

else{

if(-1 == (pid = wait(NULL))){

printf("no child progress,and wait() return -1\n");

}

else{

printf("wait() return child progress pid is %d\n",pid);

}

if(-1 == (pid = wait(NULL))){

printf("no child progress,and wait() return -1\n");

}

else{

printf("wait() return child progress pid is %d\n",pid);

}

}

}

return 0;

}

运行结果

father progress,and father progress pid is 24085

father progress forked,and child progress pid is 24086

father progress forked,and child progress pid is 24087

wait() return child progress pid is 24086

wait() return child progress pid is 24087

//当子进程有一个死循环无法终止,则父进程对应的wait(NULL)会一直阻塞,等待进程结束,所以就一直卡着程序无法终止。

#include

#include

#include

#include

int main(){

int pid;

printf("father progress,and father progress pid is %d\n",getpid());

if(0 == fork()){

printf("father progress forked,and child progress pid is %d\n",getpid());

}

else{

if(0 == fork()){

printf("father progress forked,and child progress pid is %d\n",getpid());

}

else{

if(0 == fork()){

printf("father progress forked,and child progress pid is %d\n",getpid());

while(1) ;//对应第三个wait()

}

else{

if(-1 == (pid = wait(NULL))){

printf("no child progress,and wait() return -1\n");

}

else{

printf("wait() return child progress pid is %d\n",pid);

}

if(-1 == (pid = wait(NULL))){

printf("no child progress,and wait() return -1\n");

}

else{

printf("wait() return child progress pid is %d\n",pid);

}

if(-1 == (pid = wait(NULL))){

printf("no child progress,and wait() return -1\n");

}

else{

printf("wait() return child progress pid is %d\n",pid);

}

}

}

}

return 0;

}

作用及其用法

【status为NULL】:

因为一个进程,如果fork()之后生成子进程,如果不进行wait(NULL)则当子进程退出时会出现子进程的内存无法释放的状态,因此子进程便成为了僵尸进程,而一个wait(NULL)只能等待一个子进程,只要有子进程退出,wait(NULL)退出阻塞(且返回值为退出的子进程的进程号),否则一直阻塞直到有子进程退出。当调用wait()函数的进程没有子进程时,返回-1。

【status不为NULL】:

如果参数status的值不是NULL,wait就会把子进程退出时的状态取出并存入其中,这是一个整数值(int),指出了子进程是正常退出还是非正常结束的(一个进程也可以被其他进程用信号结束),以及正常结束时返回值,或被哪一个信号结束的等信息。由于这些信息被存放在一个整数的不同二进制位中,所以用常规的方法读取会非常麻烦,人们就设计了一套专门的宏(macro)来完成这项工作,下面我们来学习一下其中最常见的两个:

1、WIFEXITED(status):这个宏用来指出子进程是否为正常退出的,如果是,它会返回一个非零值。(请注意,虽然名字一样,这里的参数status并不同意wait唯一的参数——指向整数的指针status,而是那个指针指向的整数,切记不要搞混了。)

2、WEXITSTATUS(status):当WIFEXITED返回非零值时,我们可以用这个宏来提取子进程的返回值,如果子进程调用exit(5)退出,WEXITSTATUS(status)就会返回5;如果子进程调用exit(7)退出,WEXITSTATUS(status)就会返回7。请注意,如果进程不是正常退出,也就是说,WIFEXITED返回0,这个值就毫无意义了。

问题来了,如果不用wait(),如何使一个子进程不会变成僵尸进程

答案是有的,那就是通过两个fork(),具体实现如下,通过先fork()一个子进程,然后在子进程里在fork()一个子进程,然后在退出第二个子进程,则第三个子进程会成为孤儿进程,被init收养,然后就可以实现不用wait()就可以使子进程不进入僵尸进程

#include

#include

#include

#include

#include

int main(){

pid_t pid;

if((pid = fork()) < 0){

printf("error\n");

exit(1);

}

else if(pid == 0){

if((pid = fork()) < 0){

printf("error\n");

exit(1);

}

else if(pid > 0){

exit(0); //parent from second fork == first child

}

sleep(2);

printf("second child ,parent pid = %ld\n",(long)getppid());

exit(0);

}

if(waitpid(pid,NULL,0) != pid) //wait for first pid

{

printf("error\n");

exit(1);

}

return 0;

}

运行如下

使用wait()函数有一个不方便的地方就是,一个wait()只能对应一个进程,而且无法定哪一个wait()等待的是哪一个进程,因此应该用waitpid()

(图源网络,侵删)

函数说明

如果在调用 waitpid()时子进程已经结束,则 waitpid()会立即

返回子进程结束状态值。 子进程的结束状态值会由参数 status 返回,

而子进程的进程识别码也会一起返回。如果不在意结束状态值,则

参数 status 可以设成 NULL。参数 pid 为欲等待的子进程识别码,

其他数值意义如下:

pid pid=-1 等待任何子进程,相当于 wait()。

pid=0 等待进程组识别码与目前进程相同的任何子进程。

pid>0 等待任何子进程识别码为 pid 的子进程。

参数options提供了一些额外的选项来控制waitpid,参数 option 可以为 0 或可以用"|"运算符把它们连接起来使用,比如:

ret=waitpid(-1,NULL,WNOHANG | WUNTRACED);

如果我们不想使用它们,也可以把options设为0,如:

ret=waitpid(-1,NULL,0);

WNOHANG 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若结束,则返回该子进程的ID。

WUNTRACED 若子进程进入暂停状态,则马上返回,但子进程的结束状态不予以理会。WIFSTOPPED(status)宏确定返回值是否对应与一个暂停子进程。

子进程的结束状态返回后存于 status,底下有几个宏可判别结束情况:

WIFEXITED(status)如果若为正常结束子进程返回的状态,则为真;对于这种情况可执行WEXITSTATUS(status),取子进程传给exit或_eixt的低8位。

WEXITSTATUS(status)取得子进程 exit()返回的结束代码,一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏。

WIFSIGNALED(status)若为异常结束子进程返回的状态,则为真;对于这种情况可执行WTERMSIG(status),取使子进程结束的信号编号。

WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED 来判断后才使用此宏。

WIFSTOPPED(status) 若为当前暂停子进程返回的状态,则为真;对于这种情况可执行WSTOPSIG(status),取使子进程暂停的信号编号。

WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用 WIFSTOPPED 来判断后才使用此宏。

如果执行成功则返回子进程识别码(PID) ,如果有错误发生则返回

返回值-1。失败原因存于 errno 中。

由于wait()和waitpid()本质没有什么区别所以就只写了一个相关代码

//代码

#include

#include

#include

#include

#include

int main()

{

pid_t childpid;

int status;

childpid = fork();

if ( childpid < 0 )

{

perror( "fork()" );

exit(1);

}

else if ( childpid == 0 )

{

puts( "In child process" );

sleep( 3 );//让子进程睡眠3秒,看看父进程的行为

printf("\tchild pid = %d\n", getpid());

printf("\tchild ppid = %d\n", getppid());

exit(1);

}

else

{

waitpid( childpid, &status, 0 );

puts( "in parent" );

printf( "\tparent pid = %d\n", getpid() );

printf( "\tparent ppid = %d\n", getppid() );

printf( "\tchild process exited with status %d \n", status );

}

exit(0);

}

运行

In child process

child pid = 4469

child ppid = 4468

in parent

parent pid = 4468

parent ppid = 4379

child process exited with status 0

总结

wait()函数用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或该进程接收到一个指定的信号为止。如果该父进程没有子进程或它的子进程已经结束,则wait()就会立即返回-1。而waitpid()的作用和wait()一样,但它并不一定要等待一个终止的子进程,它还有若干选项,如可提供一个非阻塞版本的wait()功能,也能支持各种作用控制。wait()函数只是waitpid()函数的一个特例,在Linux内部实现wait()函数时直接调用的就是waitpid()函数。

waitpid最后以一个参数设为0_wait()和waitpid()解析相关推荐

  1. waitpid最后以一个参数设为0_waitpid

    营销树今天精心准备的是<waitpid>,下面是详解! linux 中的waitpid函数的返回值问题 TheprocessIDofthechildwhichexited,orzeroif ...

  2. waitpid最后以一个参数设为0_西门子MM440变频器参数设置

    1.图片1.P0003为用户访问等级参数,当你无法找到你要看的参数时,不妨将其设为3试试: 2.P0004为参数过滤参数,将其设为0即可访问全部参数: 3.电机参数只有在P0010设为1时,才能更改: ...

  3. waitpid最后以一个参数设为0_详解wait和waitpid函数(转)

    #include /* 提供类型pid_t的定义 */ #include pid_t wait(int *status) 进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子 ...

  4. 不错的递归题:输入123,返回“321”。 要求必须用递归,不能用全局变量,输入必须是一个参数,必须返回字符串。

    题目:输入123,返回"321". 要求必须用递归,不能用全局变量,输入必须是一个参数,必须返回字符串. 解析:每次求得最后一个数字然后加递归剩余的数字(每次缩短一个长度).注意退 ...

  5. 一阶矩+二阶矩估计求解一个参数

    一阶矩+二阶矩估计求解一个参数 @(概率论) 一般来说,一个参数对应一个方程.所以在矩估计法中,用一阶矩就可以求解一元.但是有些情况下,只写一阶矩,原理上是可以求得解的,但是,初等代数中很难剥离出来, ...

  6. 当db_cache_advice初始化参数设为on, 大大降低了cpu的使用

    7.2.2.1 Buffer Cache Advisory Statistics A number of statistics can be used to examine buffer cache ...

  7. Firefox/Chrome下flash的wmode参数设为opaque或transparent时输入文本框中无法输入中文汉字的解决方法

    一.前言 这段时间做个项目,要涉及到flash开发.真悲催,之前没有接触过flash开发,于是找个哥们临时教了一下Adobe Flash CS5 的使用方法,感觉还蛮简单,所见即所得,和MFC下的开发 ...

  8. Firefox/Chrome下flash的wmode参数设为opaque或transparent时输入文本框中无法输入中文汉字的解决方法...

    这段时间做个项目,要涉及到flash开发.真悲催,之前没有接触过flash开发,于是找个哥们临时教了一下Adobe Flash CS5 的使用方法,感觉还蛮简单,所见即所得,和MFC下的开发有点像,渐 ...

  9. 有监督学习的算法fit(x,y)传两个参数无监督学习的算法是fit(x),即传一个参数

    有监督学习的算法fit(x,y)传两个参数无监督学习的算法是fit(x),即传一个参数 https://www.jianshu.com/p/55e261ce9b3e

最新文章

  1. 51nod 1617 奇偶数组
  2. AC日记——小书童——刷题大军 洛谷 P1926
  3. word如何书写数学公式
  4. Zend Studio添加ThinkPHP代码提示方法
  5. mysql权限的误操作的恢复
  6. 安装Maya 6.5指南
  7. SEE Conf: Umi 4 设计思路文字稿
  8. dede搜索页面上某些标签无法使用
  9. 计算机程序领域专利撰写,干货 | 计算机软件专利撰写模板
  10. smartq ten3 android4.2 v1.1,全线升级Android 4.2 智器平板新体验
  11. android手机如何查看系统版本号,怎么查看安卓系统版本
  12. 数仓学习笔记(7)——数仓搭建(DWT层)
  13. 写给那些常年战痘的痘友们~~~
  14. 什么是mx记录?如何设置域名mx记录?
  15. 独家首发|汇聚知识 理解世界——百度王海峰谈知识图谱的最新演讲笔记
  16. 运行剑灵与服务器断开,《剑灵》与服务器断开链接1000\3000的解决办法
  17. GoLang下载安装
  18. GMTC-闲鱼Flutter实践效果访谈
  19. 防骗大数据,朋友圈里卖的这些东西...不是坑人就是害命!
  20. BLHeli无刷电调 后续

热门文章

  1. 仿QQ圆头像裁剪开源项目——ClipCircleHeadLikeQQ
  2. 详解网站域名劫持原理与域名挟持的几种方法
  3. Mysql_3 ER 和 EER 模型
  4. mysql创建表语句like_MySQL 的create table as 与like 的使用
  5. SQL Server数据库的T-SQL高级查询
  6. 树链剖分求lca模板
  7. 金融经济学(王江)期末梳理第十二章 μ-σ 分析组合选择
  8. html和css的小结
  9. Smartfoxserver点滴
  10. SpringBoot修改默认网页图标