zoukankan      html  css  js  c++  java
  • wait 和waitpid函数对比-(转自 wintree)

    Wait和waipid函数

    当一个进程正常或异常终止的时候,内核就像其父进程发送SIGCHLD信号,因为子进程是个一步事件,所以这种信号也是内核系那个父进程发的异步通知。父进程可以选择忽略该信号,或者提供一个该信号发生时即被调用执行的函数。对于这种信号的系统默认动作是忽略它。

    现在要知道调用wait或waitpid的进程可能会发生什么情况:

    •  如果其所有子进程都在运行,则阻塞。
    • 如果一个子进程已经终止,正在得带的父进程获取到终止状态,则取得该子进程的终止状态立即返回。
    • 如果他没有任何子进程,则立即出错返回。

    如果进程由于接收到SIGCHLD信号而调用wait,则可期望wait会立即返回。但是如果在任意时刻调用wait则进程可能会阻塞。

    两个函数原型

    1. #include <sys/wait.h>  
    2.   
    3. pid_t wait(int *status);  
    4.   
    5. pit_t wait(pid_t pid,int *status,int options);  
    6.   
    7.    
    8.   
    9. 函数若成功,返回进程ID,若出错则返回-1;  


    下面就来一个简单的例子来展示一下我们的wait函数

    1. #include "apue.h"  
    2.   
    3. #include <sys/wait.h>  
    4.   
    5.    
    6.   
    7. int main(void)  
    8.   
    9. {  
    10.   
    11.         pid_t pid1,pid2;  
    12.   
    13.        printf("before fork ");  
    14.   
    15.           
    16.   
    17.        if((pid1=fork())<0){  
    18.   
    19.                printf("fork error");  
    20.   
    21.         }else if(pid1==0){  
    22.   
    23.                 printf("child process 'spid=%d ",getpid());  
    24.   
    25.                 sleep(3);  
    26.   
    27.         }else{  
    28.   
    29.                pid2=wait(NULL);  
    30.   
    31.                printf("wait process 's pid=%d ",pid2);  
    32.   
    33.         }  
    34.   
    35.         exit(0);  
    36.   
    37. }  


     

    输出结果:                             

    当程序运行的时候明显的可以看到在输出最后一行 的时候等待了三秒钟。也就是父进程等待子进程的结束。父进程才能扑捉子进程,然后得到wait要得到的结果。

    参数status:

    参数status是一个整型指针。如果参数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,这个值就毫无意义。

    详细的书中的表

    下面的例子就是获取到子进程的终止信号。然后进行输出。

    1. #include "apue.h"  
    2.   
    3. #include<sys/wait.h>  
    4.   
    5.    
    6.   
    7. void pr_exit(int);  
    8.   
    9.    
    10.   
    11. int main(void)  
    12.   
    13. {  
    14.   
    15.         pid_t pid;  
    16.   
    17.         int status;  
    18.   
    19.    
    20.   
    21.        if((pid=fork())<0){  
    22.   
    23.                err_sys("fork error");  
    24.   
    25.         }else if(pid==0){  
    26.   
    27.                 exit(7);  
    28.   
    29.         }  
    30.   
    31.    
    32.   
    33.        if(wait(&status)!=pid)  
    34.   
    35.                err_sys("wait error");  
    36.   
    37.         pr_exit(status);  
    38.   
    39.    
    40.   
    41.        if((pid=fork())<0)  
    42.   
    43.                err_sys("fork error");  
    44.   
    45.         else if(pid==0)  
    46.   
    47.         //      printf("child  pid=%d ",getpid());  
    48.   
    49.                  //printf("child pid=%d ",getppid());  
    50.   
    51.                 abort();  
    52.   
    53.    
    54.   
    55.         if(wait(&status)!=pid)  
    56.   
    57.                err_sys("wait error");  
    58.   
    59.         pr_exit(status);  
    60.   
    61.    
    62.   
    63.        if((pid=fork())<0)  
    64.   
    65.                err_sys("fork error");  
    66.   
    67.         else if(pid==0)  
    68.   
    69.                //printf(" parent pid=%d ",getppid());  
    70.   
    71.                  //printf("child  pid=%d ",getpid());  
    72.   
    73.                 status/=0;  
    74.   
    75.    
    76.   
    77.        if(wait(&status)!=pid)  
    78.   
    79.                err_sys("wait error");                                                                                                                                         
    80.   
    81.        pr_exit(status);                                                                                                                                                       
    82.   
    83.                                                                                                                                                                                
    84.   
    85.         exit(0);                                                                                                                                                               
    86.   
    87.                                                                                                                                                                                
    88.   
    89. }                                                                                                                                                                              
    90.   
    91.                                                                                                                                                                                
    92.   
    93. void pr_exit(int status)                                                                                                                                                       
    94.   
    95. {                                                                                                                                                                               
    96.   
    97.        if(WIFEXITED(status))                                                                                                                                                  
    98.   
    99.                printf("normal termination,exitstatus=%d ",WEXITSTATUS(status));                                                                                             
    100.   
    101.         elseif(WIFSIGNALED(status))                                                                                                                                           
    102.   
    103.                printf("abnormal termination,signalstatus=%d ",WTERMSIG(status),                                                                                             
    104.   
    105. #ifdef WCOREDUMP                                                                                                                                                               
    106.   
    107.                                WCOREDUMP(status)?"(core file generated)":"");                                                                                                 
    108.   
    109.                                                                                                                                                                                
    110.   
    111. #else                                                                                                                                                                          
    112.   
    113.                "");                                                                                                                                                           
    114.   
    115. #endif                                                                                                                                                                         
    116.   
    117.         elseif(WIFSTOPPED(status))                                                                                                                                            
    118.   
    119.                printf("child stopped ,signal number=%d ",                                                                                                                    
    120.   
    121.                                WSTOPSIG(status));                                                                                                                              
    122.   
    123.                                                                                                                                                                                
    124.   
    125. }    
    126.   
    127.    


     

    输出结果:

    从结果我们看到了调用exit为正常终止函数。

    Waitpid函数。

    当我们需要等待一个特定进程的函数时候,我们这个时候就需要用到了waitpid函数了。从上文看到waitpid函数原型,我们也都了解到有个pid_t参数。

    解释如下:

    Pid=-1,等待任一个子进程。与wait等效。

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

    Pid==0等待其组ID等于调用进程组ID的任一个子进程。

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

    Waitpid返回终止子进程的进程ID。并将该子进程的终止状态存放在有status指向的存储单元中。

    Waitpid 函数提供了wait函数没有提供的三个功能。

    Waitpid可等待一个特定的进程,而wait则返回任一个终止子进程的状态。

    Waitpid提供了yigewait费阻塞版本。有时候用户希望取得一个子进程的状态,但不想阻塞。

    Waitpid支持作业控制。

    Waitpid返回值和错误

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

    1. 当正常返回的时候,waitpid返回收集到的子进程的进程ID;
    2. 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
    3. 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;

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

    1. #include <sys/types.h>  
    2.   
    3. #include <sys/wait.h>  
    4.   
    5. #include <unistd.h>  
    6.   
    7. int main()  
    8.   
    9. {          
    10.   
    11.          pid_tpc, pr;  
    12.   
    13.          pc=fork();   
    14.   
    15.          if(pc<0){     
    16.   
    17.                    /*如果fork出错 */                 
    18.   
    19.                    printf("Erroroccured on forking. ");        
    20.   
    21.          }elseif(pc==0){                     
    22.   
    23.                    /*如果是子进程 */                 
    24.   
    25.                    sleep(10);  
    26.   
    27.                    /*睡眠10秒 */               
    28.   
    29.          exit(0);       
    30.   
    31.          }          
    32.   
    33.          /*如果是父进程 */        
    34.   
    35.          do{               
    36.   
    37.                    pr=waitpid(pc,NULL, WNOHANG);            
    38.   
    39.                    /*使用了WNOHANG参数,waitpid不会在这里等待 */                     
    40.   
    41.                    if(pr==0){                      
    42.   
    43.                    /*如果没有收集到子进程 */                           
    44.   
    45.                             printf("Nochild exited ");                           
    46.   
    47.                    sleep(1);    
    48.   
    49.                    }  
    50.   
    51.          }        while(pr==0);              
    52.   
    53.                    /*没有收集到子进程,就回去继续尝试 */        
    54.   
    55.                    if(pr==pc)            
    56.   
    57.                             printf("successfullyget child %d ", pr);           
    58.   
    59.                    else             
    60.   
    61.                             printf("someerror occured ");  
    62.   
    63. }  
    64.   
    65.    


     

    输出结果:

     

    从结果中,我们看到父进程一直在等待子进程的结束。

    wait()和waitpid()就讲解到此。有什么疑问欢迎告知。

    转载链接:http://blog.csdn.net/wallwind/article/details/6998602

  • 相关阅读:
    maven 历史版本下载地址
    eclipse 热部署
    在线代码练习
    Intellij热部署插件JRebel
    模拟数据生成器
    电脑读取U盘总提示格式化
    变形金刚
    slamdunk正在做菜
    丧心病狂的计数
    小明在工作
  • 原文地址:https://www.cnblogs.com/-colin/p/8023072.html
Copyright © 2011-2022 走看看