使用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时需要注意这一点。

 #include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include "errno.h" void SigChildFunc()
{
pid_t pid;
int status; // capture1 begin
pid = waitpid(-, &status, WNOHANG);
if(pid > )
{
printf("capture SIGCHLD1\n");
}
else
{
printf("SigChildFunc error! errno=%d\n", errno);
}
// capture1 end // capture2 begin
// pid = waitpid(-1, &status, WNOHANG);
// if(pid > 0)
// {
// printf("capture SIGCHLD2\n");
// }
// else
// {
// printf("SigChildFunc error! errno=%d\n", errno);
// }
// capture2 end
} void SignalCB(int Signal)
{
switch(Signal)
{
case SIGCHLD:
SigChildFunc();
break;
default:
break;
}
} int main()
{
signal(SIGCHLD, SignalCB); // test system begin
system("ls");
// test system end // test fork begin
// pid_t pid = fork();
// if(pid < 0)
// {
// printf("fork error! errno=%d\n", errno);
// }
// else if(pid == 0)
// {
// printf("this is child.\n");
// exit(0);
// }
//
// printf("this is parent.\n");
// sleep(3);
// test fork end return ;
}

waitpid使用的一点问题的更多相关文章

  1. 系统调用wait、waitpid和exec函数

    本文介绍了Linux下的进程的一些概念,并着重讲解了与Linux进程管理相关的重要系统调用wait,waitpid和exec函数族,辅助一些例程说明了它们的特点和使用方法. 1.7 背景 在前面的文章 ...

  2. wait、waitpid 僵尸进程 孤儿进程

    man wait: NAME wait, waitpid, waitid - wait for process to change state SYNOPSIS #include <sys/ty ...

  3. UNIX高级环境编程(9)进程控制(Process Control)- fork,vfork,僵尸进程,wait和waitpid

    本章包含内容有: 创建新进程 程序执行(program execution) 进程终止(process termination) 进程的各种ID   1 进程标识符(Process Identifie ...

  4. wait & waitpid 以及子进程传给父进程的信号分析

    wait() 和 waitpid() wait() 系统调用挂起调用进程的执行直到有一个孩子终止.调用 wait(&status) 等价于: waitpid(-1, &status, ...

  5. wait和waitpid

    当有多个子进程的SIGCHLD信号到达父进程的时候,如果父进程用wait等待,那么父进程在处理第一个达到的SIGCHLD信号的时候,其他的SIGCHLD信号被堵塞,而且信号不被缓存,这样就会导致信号丢 ...

  6. Linux网络编程wait()和waitpid()的讲解

    本文讲的是关于wait和waitpid两者的区别与联系.为避免僵尸进程的产生,无论我们什么时候创建子进程时,主进程都需要等待子进程返回,以便对子进程进行清理.为此,我们在服务器程序中添加SIGCHLD ...

  7. 转载:进程退出状态--waitpid status意义

    最近遇到一个进程突然退出的问题,由于没有注册signalhandler所以没有捕捉到任何信号. 但是从log中看到init waitpid返回的status为0x008b,以前对status不是很了解 ...

  8. fork系统调用关于如何让子进程先运行{wait(),waitpid(),sleep()}

    在父进程里面调用wait()和waitpid()可以确保子进程先运行,因为当子进程运行完后会变成僵尸进程,此时会发送一个信号给父进程,父进程接受到信号才会运行. 有人或许会问如果在父进程调用wait之 ...

  9. 关于自己写C++的一点风格

    现在,我学了很长时间的C++,但是自己就是无法精通.许多知识是入门书上没有的.现在写C++最重要的就是风格问题. 我现在的C++风格: 把自己所有的东西都放在一个名称空间下. 没有全局的函数,有的函数 ...

随机推荐

  1. NoSQL-MongoDB with python

    前言: MongoDB,文档存储型数据库(document store).NoSQL数据库中,它独占鳌头,碾压其他的NoSQL数据库. 使用C++开发的,性能仅次C.与redis一样,开源.高扩展.高 ...

  2. Kotlin——初级篇(四):控制语句详解

    在前面 的章节中讲解了Kotlin语言中的数据类型.变量与常量的定义.不了解请参见前面的内容: Kotlin--初级篇(三):数据类型详解. Kotlin--初级篇(二)常量.变量.注释. 下面详细为 ...

  3. CODEVS 必做题:3149、2821、1531、3369、1230

    3149 爱改名的小融 2  时间限制: 2 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description Wikioi上有个人叫小融,他喜 ...

  4. 1105 第K大的数(二分)

    1105 第K大的数 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 数组A和数组B,里面都有n个整数.数组C共有n^2个整数,分别是A[0] * B[0],A[0 ...

  5. 项目中调用ExcelCom组件时的配置流程

    异常提示如下:         Microsoft Office Excel 不能访问文件“*.xls”. 可能的原因有:        1 文件名称或路径不存在.       2 文件正被其他程序使 ...

  6. this.$apply()

    chooseVideo(e) { this.fileInfo = {} let that = this wx.chooseVideo({ sourceType: ['album', 'camera'] ...

  7. badboy脚本参数化和检查点

    一.badboy脚本参数化 文本参数化 方式一:直接在Variablesl ist添加参数化变量和值,然后在Script里面找到对应需要参数化的内容-属性,进行替换,参数化名需要用${XX}引用: 方 ...

  8. android自定义控件(二)Canvas

    一.重要方法 1.translate 2.scale 3.rotate 二.注意 1.明确顺序 canvas.rotate(45); canvas.drawRect(new Rect(50, 50, ...

  9. Python基础-re正则模块

    一.简介: 正则表达式:是一种小型的.高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过re模块实现,正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎执行. 二.字 ...

  10. 算法题 18 像素翻转 牛客网 CC150

    算法题 18 像素翻转 牛客网 CC150_P114 题目描述 有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时 ...