zoukankan      html  css  js  c++  java
  • wait和waitpid

    wait和waitpid

    当用fork启动一个子进程时,子进程就有了它自己的生命周期并将独立运行。有时,我们希望知道一个子进程何时结束。对于许多需要创建子进程的应用来说,父进程能够监测子进程的终止时间和过程是很有必要的。wait()以 及若干相关的系统调用提供了这一功能。

    1.wait

    系统调用wait()等待调用进程的任一子进程终止,同时在参数status所指向的缓冲区中返回该子进程的终止状态。

    1 #include<sys/types.h>  
    2 #include<sys/wait.h>  
    3 pid_t wait(int *status);  
    4 //返回:若成功则为进程ID,若出错则为-1  

    系统调用wait()执行如下动作。

    1.如果调用进程之前并无未被等待的子进程终止,调用将一直阻塞, 直至某个子进程终止。如果调用时已有子进程终止,wait()则立即返回。

    2.如果status非空,那么关于子进程如何终止的信息则会通过status指向的整型变量返回。

    3.内核将会为父进程下所有子进程的运行总量追加进程CPU时间以及资源使用

    数据。

    4.将终止子进程的ID作为wait()的结果返回。出错时,wait()返回-1。 可能的错误原因之一是调用进程之前并无未被等待的子进程,此时会将errno置为ECHILD。

    例1:

     1 #include<stdio.h>
     2 #include<sys/types.h>
     3 #include<sys/wait.h>
     4 #include<unistd.h>
     5 #include<stdlib.h>
     6 #include<errno.h>
     7 #include<math.h>
     8 #include<string.h>
     9 
    10 int main()
    11 {
    12     pid_t child;
    13     //创建进程
    14     if((child=fork())==-1)
    15     {
    16         printf("Fork Error :%s
    ",strerror(errno));
    17         exit(EXIT_FAILURE);
    18     }
    19     else
    20     {
    21         if(child==0)
    22         {
    23             printf("the child process is run
    ");
    24             sleep(1);//子进程睡眠一秒
    25             printf("I am child: %d
    ",getpid());
    26             exit(EXIT_SUCCESS);
    27         }
    28         else
    29         {
    30             int j=0;
    31             j=wait(NULL);//等待子进程退出,父进程运行
    32             printf("the father process is run
    ");
    33             printf("the child process ID is %d
    ",j);
    34             printf("I am the father :%d
    ",getpid());
    35             return 0;
    36         }    
    37     }
    38 }

    我们可以看见父进程是在子进程运行结束之后才运行的。

    现在我们尝试等待多个子进程:

    例2:

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <sys/wait.h>
     4 #include <unistd.h>
     5 #include <stdlib.h>
     6 #include <errno.h>
     7 #include <string.h>
     8 
     9 
    10 int main(int argc,char * argv[])
    11 {
    12     pid_t childPid;
    13     
    14     printf("fork program starting
    ");
    15     
    16     for(int j=1;j<5;j++){
    17         switch(fork())
    18         {
    19             case -1:
    20                 perror("fork failed");
    21                 exit(EXIT_FAILURE);
    22             
    23             case 0:
    24                 printf("I am child. My PID %d, 
    ",getpid());
    25                 sleep(1);
    26                 _exit(EXIT_SUCCESS);
    27             default:
    28                 break;
    29         }
    30     }
    31     //循环等待
    32     while((childPid = wait(NULL)) != -1)
    33     {
    34         
    35         sleep(1);
    36         printf("wait childPid is %d
    ",childPid);
    37         
    38     }
    39     if(errno !=ECHILD)
    40             exit(EXIT_FAILURE);
    41     
    42 }

    结果:

    我们可以很清楚的看见父进程创建了多个进程,但是父进程不能通过wait指定的等待某一个子进程。只能按顺序的等待下一个子进程的终止。并且如果没有子进程的退出,wait()总是被阻塞的。

    2.waitpid

    系统调用wait(存在诸多限制,而设计waitpidO则意在突破这些限制。

    1.如果父进程已经创建了多个子进程,使用wait()将无法等待某个特定子进程的完成,只能按顺序等待下一个子进程的终止。

    2.如果没有子进程退出,wait()总是保持阻塞。有时候会希望执行非阻塞的等待:是否有子进程退出,立判可知。

    3.使用wait(只能发现那些已经终止的子进程。对于子进程因某个信号(如SIGSTOP或SIGTTIN)而停止,或是已停止子进程收到SIGCONT信号后恢复执行的情况就无能为力了。

    1. #include<sys/types.h>    
    2. #include<sys/wait.h>    
    3. pid_t waitpid(pid_t pid,int *status,int options);    
    4. //返回:若成功则为进程ID,若出错则为-1    

    对于waitpid的pid参数的解释与其值有关:

    • pid == -1 等待任一子进程。于是在这一功能方面waitpid与wait等效。

    • pid > 0 等待其进程ID与pid相等的子进程。

    • pid == 0 等待其组ID等于调用进程的组I D的任一子进程。

    • pid < -1 等待其组ID等于pid的绝对值的任一子进程。

    而该子进程的终止状态则通过status 返回。

    options参数使我们能进一步控制waitpid的操作。

    参数options是一个位掩码(bit mask),可以包含( 按位或操作) 0个或多下标志(均在SUSv3中加以规范)。

    WUNTRACED:

    除了返回终止子进程的信息外,还返回因信号而停止的子进程信息。

    WCONTINUED: (自Linux2.6.10以来)

    返回那些因收到SIGCONT信号而恢复执行的已停止子进程的状态信息。

    WNOHANG:

    如果参数pid所指定的子进程并未发生状态改变,则立即返回,而不会阻塞,亦即poll (轮询)。在这种情况下,waitpid()返回0。如果调用进程并无与pid匹配的子进程,则waitpid()报错,

    将错误号置为ECHILD。

    参考资料

    Linux/Unix系统编程手册

    Unix环境高级编程

    Linux程序设计

  • 相关阅读:
    函数(五)——装饰器,递归调用,匿名函数
    函数(四)——装饰器
    函数(三)
    函数(二)
    函数(一)
    python基础(九)
    python基础(八)
    python基础(七)
    javaweb开发 idea ssm开发(二)
    PHP计算两个经纬度地点之间的距离
  • 原文地址:https://www.cnblogs.com/mumu597/p/12903227.html
Copyright © 2011-2022 走看看