zoukankan      html  css  js  c++  java
  • 二十四、Linux 进程与信号---wait 函数

    24.1 wait 函数说明

     24.1.1 waitpid---等待子进程中断或结束

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

    1 #include <sys/types.h>
    2 #include <sys/wait.h>
    3 pid_t waitpid(pid_t pid,int * status,int options);
    • 函数说明
      • waitpid() 会暂时停止目前进程的执行,直到有信号来到或子进程结束。
      • 如果在调用 wait() 时子进程已经结束,则 wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数 status 返回,而子进程的进程识别码也会一快返回。
      • 如果不在意结束状态值,则参数status可以设成NULL。
    • 函数功能:wait 函数的非阻塞版本
    • 函数参数
      • @pid 为欲等待的子进程识别码,其他数值意义如下:
        • pid< -1 等待其组ID等于 pid 的绝对值的任一子进程
        • pid= -1 等待任一子进程,相当于wait()。
        • pid= 0 等待进程组 ID 等于调用进程的组 ID 的任一子进程
        • pid> 0  等待其进程ID 与 pid 相等的子进程。
      • @option可以为0 或下面的OR 组合
        • WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。(若由 pid 指定的子进程没有退出,则立即返回,则 waitpid 不阻塞,此时其返回值为0,若不设置就为阻塞,相当于wait)
        • WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。(若某实现支持作业控制,则由 pid 指定的任一子进程状态已暂停,且其状态自暂停以来还未报告过,则返回其状态)
      • @status 子进程的结束状态返回后存于 status,底下有几个宏可判别结束情况
        • WIFEXITED(status)  如果子进程正常结束则为非0值。
        • WEXITSTATUS(status)  取得子进程 exit() 返回的结束代码,一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏。
        • WIFSIGNALED(status)  如果子进程是因为信号而结束则此宏值为真(接到一个不能捕捉的信号)
        • WTERMSIG(status)  取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED 来判断后才使用此宏。
        • WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为真。一般只有使用 WUNTRACED  时才会有此情况。
        • WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用 WIFSTOPPED  来判断后才使用此宏。
    • 返回值
      • 如果执行成功则返回子进程识别码(PID),如果有错误发生则返回 -1 。失败原因存于 errno 中。

    24.1.2 wait --- 等待子进程中断或结束

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

    1 #include <sys/types.h>
    2 #include <sys/wait.h>
    3 pid_t wait (int * status);
    • 函数说明
      • wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。
      • 如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数 status 返回,而子进程的进程识别码也会一快返回。
      • 如果不在意结束状态值,则参数 status 可以设成 NULL。子进程的结束状态值请参考waitpid()。
    • 函数功能:等待子进程退出并回收,防止僵尸进程产生
    • 函数参数
      • @status:为空时,代表任意状态结束的子进程,若不为空,则代表指定状态结束的子进程  
    • 返回值
      • 如果执行成功则返回子进程识别码 (PID),如果有错误发生则返回 -1 。失败原因存于 errno 中。

    24.1.3 wait 和 waitpid 函数的区别

    • 在一个子进程终止前,wait 使其调用者阻塞
    • waitpid 由一个选择项,可使调用者不阻塞
    • waitpid 等待一个指定的子进程,而 wait 等待所有的子进程,返回任一终止子进程的状态  

    24.2 案例

    24.2.1 wait 函数

      process_wait.c

     1 #include <sys/types.h>
     2 #include <sys/wait.h>
     3 #include <unistd.h>
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 
     7 
     8 void out_status(int status)
     9 {
    10     if(WIFEXITED(status)) {
    11         printf("normal exit: %d
    ", WEXITSTATUS(status));
    12     } else if(WIFSIGNALED(status)) {
    13         printf("abnormal term: %d
    ", WTERMSIG(status));
    14     } else if(WIFSTOPPED(status)) {
    15         printf("stopped sig: %d
    ", WSTOPSIG(status));
    16     } else {
    17         printf("unkown sig
    ");
    18     }
    19 }
    20 
    21 int main(void)
    22 {
    23     int status;//存储子进程终止返回的状态
    24     pid_t pid;
    25 
    26     /* 正常终止 */
    27     if((pid = fork()) < 0) {
    28         perror("fork error");
    29         exit(1);
    30     } else if(pid == 0) {
    31         printf("pid: %d, ppid: %d
    ", getpid(), getppid());
    32         exit(3);//子进程终止运行
    33     }
    34 
    35     //父进程调用wait函数阻塞,等待子进程结束并回收
    36     wait(&status);
    37     out_status(status);
    38     printf("==========================
    ");
    39 
    40     /* 非正常终止 */
    41     if((pid = fork()) < 0) {
    42         perror("fork error");
    43         exit(1);
    44     } else if(pid == 0) {
    45         printf("pid: %d, ppid: %d
    ", getpid(), getppid());
    46         int i = 3;
    47         int j = 0;
    48         int k = i / j;
    49         printf("k: %d
    ", k);
    50     }
    51 
    52     wait(&status);
    53     out_status(status);
    54     printf("==========================
    ");
    55 
    56     /* 暂停 */
    57     if((pid = fork()) < 0) {
    58         perror("fork error");
    59         exit(1);
    60     } else if(pid == 0) {
    61         printf("pid: %d, ppid: %d
    ", getpid(), getppid());
    62         pause();//暂停,即为阻塞,等待一个信号将它继续运行
    63         /*
    64         int i = 0;
    65         while(++i > 0) sleep(3);*/
    66     }
    67 
    68     wait(&status);
    69     out_status(status);
    70 
    71     return 0;
    72 }

      编译运行:

      

      另开一终端,对进程发出停止信号发现无法停止:

      

      这是因为 WIFSTOPPED(status) 和 WSTOPSIG(status) 必须在使用 waitpid 的 option 参数 WUNTRACED  时候才生效,wait 函数无此功能

    22.2.2 waitpid

      process_waitpid.c

     1 #include <sys/types.h>
     2 #include <sys/wait.h>
     3 #include <unistd.h>
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 
     7 
     8 void out_status(int status)
     9 {
    10     if(WIFEXITED(status)) {
    11         printf("normal exit: %d
    ", WEXITSTATUS(status));
    12     } else if(WIFSIGNALED(status)) {
    13         printf("abnormal term: %d
    ", WTERMSIG(status));
    14     } else if(WIFSTOPPED(status)) {
    15         printf("stopped sig: %d
    ", WSTOPSIG(status));
    16     } else {
    17         printf("unkown sig
    ");
    18     }
    19 }
    20 
    21 int main(void)
    22 {
    23     int status;//存储子进程终止返回的状态
    24     pid_t pid;
    25 
    26     /* 正常终止 */
    27     if((pid = fork()) < 0) {
    28         perror("fork error");
    29         exit(1);
    30     } else if(pid == 0) {
    31         printf("pid: %d, ppid: %d
    ", getpid(), getppid());
    32         exit(3);//子进程终止运行
    33     }
    34 
    35     //父进程调用wait函数阻塞,等待子进程结束并回收
    36     wait(&status);
    37     out_status(status);
    38     printf("==========================
    ");
    39 
    40     /* 非正常终止 */
    41     if((pid = fork()) < 0) {
    42         perror("fork error");
    43         exit(1);
    44     } else if(pid == 0) {
    45         printf("pid: %d, ppid: %d
    ", getpid(), getppid());
    46         int i = 3;
    47         int j = 0;
    48         int k = i / j;
    49         printf("k: %d
    ", k);
    50     }
    51 
    52     wait(&status);
    53     out_status(status);
    54     printf("==========================
    ");
    55 
    56     /* 暂停 */
    57     if((pid = fork()) < 0) {
    58         perror("fork error");
    59         exit(1);
    60     } else if(pid == 0) {
    61         printf("pid: %d, ppid: %d
    ", getpid(), getppid());
    62         pause();//暂停,即为阻塞,等待一个信号将它继续运行
    63         /*
    64         int i = 0;
    65         while(++i > 0) sleep(3);*/
    66     }
    67 
    68     do{
    69         //子进程若结束,则 pid 为子进程编号
    70         //WNOHANG 非阻塞,waitpid 即子进程还没结束,waitpid 直接返回
    71         pid = waitpid(pid, &status, WNOHANG | WUNTRACED);
    72         if(pid == 0) sleep(1);//pid = 0, 则子进程没有结束,则父进程睡眠 1 s
    73     }while(pid == 0);
    74     out_status(status);
    75 
    76     return 0;
    77 }

      编译测试与 process_wait.c 一样

      再次发出 kill -19 pid:

      

     

  • 相关阅读:
    A Bug's Life(削弱版食物链)
    The Suspects
    Find The Multiple
    Lake Counting(dfs)
    经典dfs(depth-first search)
    喝啤酒(预防老年痴呆的深度搜索)
    C语言的位运算的优势 !
    Oil Deposits
    Catch That Cow
    HTML 003 元素
  • 原文地址:https://www.cnblogs.com/kele-dad/p/9147612.html
Copyright © 2011-2022 走看看