wait函数和僵尸进程(APUE)

本文介绍了僵尸进程的概念及其形成过程,并通过示例程序展示了如何使用wait函数回收子进程,避免僵尸进程的出现。同时,文章还详细解释了waitpid函数的参数及返回值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

wait函数和僵尸进程(APUE)

wait和waitpid函数原型:

1 #include <sys/wait.h>
2 
3 pid_t wait(int *status);
4 pid_t waitpid(pid_t pid, int *status, int options);

当进程正常或者异常终止时,内核就像其父进程发送SIGHLD信号,因为子进程终止是个异步信号,所以这种信号也是内核向父进程发的异步通知。对于这种信号,系统默认动作是忽略它,此时进程状态一直保存在内存中,直到父进程使用wait函数收集状态信息,才清空。用wait来等待一个子进程终止运行叫回收进程,如果一个子进程终止后,父进程没有调用wait函数收集信息,子进程就会变成僵尸进程,僵尸进程不占有内存资源,仅仅在进程表中保留位置,占用进程ID。当子进程变成僵尸进程后,我们可以选择杀死父进程,这样init进程就会处理该僵尸进程。

下面看看僵尸进程的形成

复制代码
 1 #include "apue.h"
 2 #include <sys/wait.h>
 3 
 4 int
 5 main(void)
 6 {
 7     pid_t pid;
 8     if((pid = fork()) < 0)
 9       err_sys("fork error");
10     else if(pid == 0)
11       printf("This is child process with pid of %d\n", getpid());
12     else{
13         sleep(20);
14         printf("This is parent process with pid of %d\n", getpid());
15     }
16     exit(0);
17 }
复制代码

编译程序,运行。

1 $ gcc test_zombie.c 
2 $ ./a.out

同时打开另外一个终端:

1 $ ps -C a.out -o ppid,pid,stat,cmd
2  PPID   PID STAT CMD
3  3649  3887 S+   ./a.out
4  3887  3888 Z+   [a.out] <defunct>

可以看到,子进程PID=3888退出(exit(0))后成为僵尸进程(stat为Z)。

调价wait() 调用。

复制代码
 1 #include "apue.h"
 2 #include <sys/wait.h>
 3 
 4 int
 5 main(void)
 6 {
 7     pid_t pid;
 8     if((pid = fork()) < 0)
 9       err_sys("fork error");
10     else if(pid == 0)
11       printf("This is child process with pid of %d\n", getpid());
12     else{
13         printf("I catched a child process with pid of %d\n", wait(NULL));
14         sleep(20);
15         printf("This is parent process with pid of %d\n", getpid());
16     }
17     exit(0);
18 }
复制代码

输出结果:

1 $ ps -C a.out -o ppid,pid,stat,cmd
2  PPID   PID STAT CMD
3  3649  4100 S+   ./a.out
1 $ ./a.out 
2 This is child process with pid of 4101
3 I catched a child process with pid of 4101
4 This is parent process with pid of 4100

 

waitpid函数(摘自网络):

参数pid的值有以下几种类型:

  pid>0时,只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去.

  pid=-1时,等待任何一个子进程退出,没有任何限制,此时waitpid和wait的作用一模一样.

  pid=0时,等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬.

  pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值.

  参数options的值有以下几种类型:

  如果使用了WNOHANG参数,即使没有子进程退出,它也会立即返回,不会像wait那样永远等下去.

  如果使用了WUNTRACED参数,则子进程进入暂停则马上返回,但结束状态不予以理会.

  Linux中只支持WNOHANG和WUNTRACED两个选项,这是两个常数,可以用"|"运算符把它们连接起来使用,比如:

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

  如果我们不想使用它们,也可以把options设为0,如:ret=waitpid(-1,NULL,0);

  waitpid的返回值比wait稍微复杂一些,一共有3种情况:

     当正常返回的时候waitpid返回收集到的子进程的进程ID;

  如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;

  如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;

  当pid所指示的子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid就会出错返回,这时errno被设置为ECHILD.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LuckyJiang.2021

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值