【Linux系统编程】进程等待

对于学习进程等待,先弄清楚下面几个问题:

什么是进程等待?

进程等待其实就是通过系统调用wait/waitpid对子进程的执行状态(执行过程中发生的异常;子进程执行结束返回的退出码)进行检测与回收子进程。

为什么要进程等待?

1、当在父进程中fork创建了一个子进程,子进程执行完毕先退出后(此时子进程的状态就是僵尸状态Z)父进程如果对其不管不顾,就无法释放创建的子进程导致内存泄漏,指令kill -9 PID只会让子进程提前退出。

2.父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。

怎么进行进程等待?

父进程通过系统调用wait/waitpid进行对僵尸进程的回收。

wait

返回值: 成功返回被等待进程 pid ,失败返回 -1
参数: 输出型参数,获取子进程退出状态 , 不关心则可以设置成为 NULL

注意:如果子进程一直不退出,父进程默认在调用wait等待子进程的时候,此时父进程处于阻塞状态。

父进程等待单个子进程:

testwait.c

 1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 #include <sys/types.h>
  5 #include <sys/wait.h>
  6 int main()
  7 {
  8   pid_t id = fork();
  9   if(0 == id)
 10   {
 11     int cnt = 6;
 12     while(cnt)
 13     {
 14       printf("i am child pid:%d cnt:%d\n", getpid(), cnt);
 15       cnt--;
 16       sleep(1);
 17     }
 18   }
 19   else if(id > 0)
 20   {
 21     int cnt = 10;
 22     while(cnt)
 23     {
 24       printf("i am parent pid:%d cnt:%d\n", getpid(), cnt);
 25       cnt--;                                                                                                                                                             
 26       sleep(1);
 27     }
 28     pid_t tmp = wait(NULL);
 29     if(tmp > 0)
 30       printf("wait success pid:%d\n", id);
 31     else
 32       printf("wait fail\n");
 33     sleep(10);
 34   }
 35   return 0;
 36 }

检测结果:

上述结果证明父进程成功等待了退出的子进程。

父进程等待多个子进程:

 testwait.c

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 #include <sys/types.h>
  5 #include <sys/wait.h>
  6 
  7 #define NUM 5
  8 
  9 void runChild()
 10 {
 11   int cnt =5;
 12   while(cnt)
 13   {
 14     printf("i am child pid:%d ppid:%d\n", getpid(), getppid());
 15     sleep(1);
 16     cnt--;
 17   }
 18 }
 19 int main()
 20 {
 21   for(int j= 0;j<NUM;j++)
 22   {
 23     pid_t tmp = fork();
 24     if(0 == tmp)
 25     {
 26       runChild();
 27       exit(1);
 28     }
 29     printf("i am parent pid:%d\n", getpid());
 30   }
 31   sleep(10);
 32   for(int i=0;i<NUM;i++)
 33   {
 34     pid_t ret = wait(NULL);
 35     if(ret>0)
 36       printf("wait success\n");
 37     else
 38       printf("wait fail\n");
 39   }
 40   sleep(10);                                                                                                                                                             
 41   return 0;
 42 }

 根据上面试验结果可以看出父进程成功等待了退出的子进程。

waitpid

返回值:
当正常返回的时候 waitpid 返回收集到的子进程的进程pid
如果设置了选项 WNOHANG, 而调用中 waitpid 发现没有已退出的子进程可收集 , 则返回 0
如果调用中出错 , 则返回 -1, 这时 errno 会被设置成相应的值以指示错误所在;
参数:
pid
pid=-1, 等待任一个子进程。与 wait 等效。
pid>0, 等待其进程pid pid 相等的子进程。
status:
WIFEXITED(status) : 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出(即子进程没有发生异常终止退出))
WEXITSTATUS(status) : WIFEXITED 非零,提取子进程退出码。(查看进程的退出码)

这里介绍一下参数status :

status是输出型参数:就是通过传入我们自己定义的整型变量的地址status可以得到操作系统内核的信息(即得到子进程执行情况的信息)。

status一共是32bit位,最后7位储存子进程异常终止的信息;次8位存储子进程退出状态(退出码)。satus在写代码时是需要我们自己定义的变量

options:
WNOHANG: pid 指定的子进程没有结束,则 waitpid() 函数返回 0 ,不予以等待。若正常结束,则返回该子进程的pid
非阻塞轮询:此时父进程的状态就不是阻塞状态了,父进程可以通过while循环对子进程进行轮询,在此轮询子进程期间父进程可以做它自己的任务。子进程退出则父进程就等待子进程,进而回收子进程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值