zoukankan      html  css  js  c++  java
  • waitpid()设置WNOHANG位(非阻塞模式)判断子进程的状态是否有所改变

    参考《Linux/Unix系统编程手册》26.1.5,对于系统调用waitid()

    #include <sys/wait.h>
    
    int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);

    若在option中设置WNOHANG位,与那么该系统调用就是非阻塞的,也就是说会立刻返回而不是等待子进程的状态发生变化。

    如果子进程的状态(正在运行or正常退出or被信号终止or被信号停止)发生变化,则会把状态具体信息保存在类型为siginfo_t结构的变量中。

    PS:在sigaction处理信号时,也可以选用这个结构。

    书上特意强调了一种情况,那就是,对于这种非阻塞操作假如子进程状态并未发生变化(也就是说正在运行,阻塞状态也可以算作未发生变化),infop指向的结构信息不会发生任何变化,因此需要预先memset将infop指向的结构每一位置为0,如果调用waitid()之后仍为0,则代表子进程状态未发生变化(简单来讲可理解为未退出)。

    siginfo_t info;
    // TODO:设置好waitid()的几个参数idtype、id、options
    // ...
    memset(&info, 0, sizeof(siginfo_t));
    if (waitid(idtype, id, &info, options | WNOHANG) == -1)
        // TODO: 错误处理
        exit(1);
    if (info.si_pid == 0) {
        // 子进程状态未发生改变
    } else {
        // 子进程状态发生改变,状态信息存储到了info中
    }

    然后我就想到了,如果是使用waitpid()呢?

    #include <sys/wait.h>
    
    pid_t waitpid(pid_t pid, int *status, int options);

    waitpid()仅仅将状态保存在int变量status中,书上很多代码是像这样

    int status;
    if (waitpid(pid, &status, options) == -1) {
        // TODO: 错误处理
        exit(1);
    }

    这有个问题,就是status并没有进行初始化,以前写C++的时候,记住的一条准则就是别忘记给变量赋初值。但是发现在很多C代码中都没有这个行为,之前在哪里看过这有利于检查错误,因为往往未赋初值的变量会导致错误,于是一直就这么写下来了。

    于是我在写了份测试代码:调用fork()创建进程,子进程休眠1秒就_exit(1)退出,父进程则立刻调用waitpid(childPid, &status, WNOHANG);

    理论上父进程的waitpid返回0(调用成功),因为childPid是对的,但是status状态千奇百怪,后来发现原因就是:子进程状态未发生改变时,status的值不变,于是status就是系统默认初始值(并未确定)。

    按照waitid()的思路,就是给status一个初值,然后检查调用waitpid()调用后status的值是否发生了变化。

    问题就来了,status该设为什么值呢?

    其实这里设为-1就行了。

    那么有人会问,如果_exit(-1);退出呢?

    退出码是个1字节的整型,而int至少占2个字节,也就是初始状态为11111111 11111111

    而如果waitpid()得到的status为-1,其实是1个字节,转换成2个字节int后就是11111111 00000000(小端模式下),和原来的-1有所不同。

    实验结果也证明了这点

    第1个结果是子进程阻塞,status不变,因此状态status为最初的-1,未知

    第2个结果是父进程先阻塞再调用waitpid(),此时子进程已经_exit(-1)退出了,状态status经过WEXITSTATUS转换后是255,即(unsigned char)-1。

  • 相关阅读:
    git fetch 和git pull 的差别
    解决npm install安装慢的问题
    Git本地分支和远程分支关联
    phalapi 2.14 使用(一)增加顶级命名空间、调整返回结构字段
    vue-element-template实战(五) 获取后端路由表动态生成权限
    vue-element-template实战(四)使用mock数据,新增用户管理界面
    使用phalapi 2.14版本的问题及解决办法
    关于vue
    git详细操作
    三次握手四次挥手理解
  • 原文地址:https://www.cnblogs.com/Harley-Quinn/p/7157579.html
Copyright © 2011-2022 走看看