zoukankan      html  css  js  c++  java
  • waitpid使用的一点问题

    使用waipid的时候遇到了一个奇怪的问题,将情况简化后描述一下。

    有关waitpid的基本介绍参见这里一下:http://www.cnblogs.com/mickole/p/3187770.html

    示例代码如下所示。主进程会处理SIGCHLD信号,处理过程是等待子进程结束,如果子进程正常退出,打印捕获到了SIGCHLD信号,否则打印错误码。让主进程后面sleep 3s是为了防止主进程先于子进程退出,从而没办法响应子进程的退出信号。

    测试正常fork的情况

    注释掉capture2和test system部分,使用capture1和test fork。

    正常的情况输出

    this is parent.
    this is child.
    capture SIGCHLD1

    视乎执行顺序,前两句有可能顺序反过来,即先执行子进程,后执行主进程后面的部分

    测试system函数的情况

    注释掉capture2和test fork部分,使用capture1和test system部分。

    输出如下

    a.out waitpid.c
    SigChildFunc error! errno=10

    可见这里waitpid出错了,没得到子进程的退出状态,其中errno 10表示No child processes(errno定义见http://baike.baidu.com/view/3485007.htm),不过并不妨碍system正确执行命令。

    原因在于system函数内部会经历fork()->exec()->waitpid()三个阶段,而我们的主函数中有处理SIGCHLD信号,里面还有waitpid操作。system本身的waitpid操作已经为子进程收尸过了,后面那个就会找不到子进程。处理的一种方式可以参见http://www.verydemo.com/demo_c167_i3191.html中的故事,我使用了另一种方式:即只waitpid我fork出的子进程,别的忽略掉,即waitpid的第一个参数不传-1,而是child_pid。

    测试连续两次waitpid的情况

    注释掉test system,使用capture1、capture2和test fork部分。

    输出如下

    this is parent.
    this is child.
    capture SIGCHLD1
    SigChildFunc error! errno=10

    同样得到了一次errno=10的错误。这说明不能连续尝试2次waitpid。

    题外话

    在lua中,os.execute等同于c中的system函数,因此如果主进程执行lua逻辑,同时在处理SIGCHLD信号时使用waitpid捕获子进程退出状态,那么lua中使用os.execute时需要注意这一点。

     1 #include <sys/wait.h>
     2 #include <sys/types.h>
     3 #include <unistd.h>
     4 #include <stdlib.h>
     5 #include <stdio.h>
     6 #include "errno.h"
     7 
     8 void SigChildFunc()
     9 {
    10     pid_t pid;
    11     int status;
    12 
    13     // capture1 begin
    14     pid = waitpid(-1, &status, WNOHANG);
    15     if(pid > 0)
    16     {
    17         printf("capture SIGCHLD1
    ");
    18     }
    19     else
    20     {
    21         printf("SigChildFunc error! errno=%d
    ", errno);
    22     }
    23     // capture1 end
    24 
    25     // capture2 begin
    26 //    pid = waitpid(-1, &status, WNOHANG);
    27 //    if(pid > 0)
    28 //    {
    29 //        printf("capture SIGCHLD2
    ");
    30 //    }
    31 //    else
    32 //    {
    33 //        printf("SigChildFunc error! errno=%d
    ", errno);
    34 //    }
    35     // capture2 end
    36 }
    37 
    38 void SignalCB(int Signal)
    39 {
    40     switch(Signal)
    41     {
    42         case SIGCHLD:
    43             SigChildFunc();
    44             break;
    45         default:
    46             break;
    47     }
    48 }
    49 
    50 int main()
    51 {
    52     signal(SIGCHLD, SignalCB);
    53 
    54     // test system begin
    55     system("ls");
    56     // test system end
    57 
    58     // test fork begin
    59 //    pid_t pid = fork();
    60 //    if(pid < 0)
    61 //    {
    62 //        printf("fork error! errno=%d
    ", errno);
    63 //    }
    64 //    else if(pid == 0)
    65 //    {
    66 //        printf("this is child.
    ");
    67 //        exit(0);
    68 //    }
    69 //
    70 //    printf("this is parent.
    ");
    71 //    sleep(3);
    72     // test fork end
    73 
    74     return 0;
    75 }
  • 相关阅读:
    PAT:1006(换个格式输出整数想&#183;)
    PAT 1008(数组循环右移问题)
    kaliLinux 工具dmitry参数解析
    PAT 1004(成绩排名)(C++)
    PAT乙级:我要通过(1003)
    PAT乙级:写出这个数(1002)
    PAT乙级:(3n+1)猜想 (1001)
    Linux初体验
    C语言基础入门:起源
    Linux_ pipe 匿名管道 浅解
  • 原文地址:https://www.cnblogs.com/njucslzh/p/3711612.html
Copyright © 2011-2022 走看看