入门客AI创业平台(我带你入门,你带我飞行)
博文笔记

linux下同时使用wait和SIGCHLD的信号处理函数

创建时间:2012-11-17 投稿人: 浏览次数:3155

前一段时间写代码用到了子进程,设置了SIGCHLD的信号处理函数,并且父进程使用wait等待子进程结束,运行的结果和我想象的不大一样。

原型抽取如下:

/*
 * SigChld.cpp
 *
 *  Created on: 2012-11-16
 *      Author: hf
 */
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
using namespace std;

void fun()
{

	cout << "fun begin" << endl;
	int n = execl("/home/hf/workspace/Hello/src/tellPid", "ls", NULL);
	if (-1 == n)
	{
		cout << "fun error" << endl;
	}
	cout << "fun end" << endl;
}

void sig_chld(int signo)
{
	pid_t pid;
	int stat;
	cout << "in sig_chld" << endl;
	if (signo == SIGCHLD)
	{
		cout << "in sig_chld sigchld" << endl;
	}
	while ((pid = waitpid(-1, &stat, WNOHANG)) > 0)
	{
		cout << "进程:" << pid << "结束" << endl;
	}
}
void sig_chld1(int signo)
{
	pid_t pid;
	int stat;
	cout << "in sig_chld1" << endl;
	if (signo == SIGCHLD)
	{
		cout << "in sig_chld1 sigchld" << endl;
	}
	while ((pid = waitpid(-1, &stat, WNOHANG)) > 0)
	{
		cout << "进程1:" << pid << "结束" << endl;
	}
}
int main()
{

	cout << "main begin" << endl;
	signal(SIGCHLD, sig_chld);
	signal(SIGCHLD, sig_chld1);
	int n = fork();
	switch (n)
	{
	case 0:
		cout << "child:" << getpid() << endl;
		sleep(7);
		fun();
		cout << "child end" << endl;
		exit(0);
		break;
	case -1:
		cout << "fork error" << endl;
		break;
	default:
		cout << "parent,child pid:" << n << endl;
		break;
	}
	int status = 0;
	int tt = wait(&status);
	cout << "wait:" << tt << endl;
	cout << "main end" << endl;
}


在父进程中使用wait等待子进程结束,同时设置了SIGCHLD的信号处理函数,此处理函数中使用waitpid来回收资源。

执行的时候发现,wait函数正常执行,并且返回了子进程的pid,信号处理函数也能够进入,但是waitpid函数不在能够收集到子进程的信息。

在网上搜索了一下,在http://www.cnblogs.com/taobataoma/archive/2007/08/30/875743.html发现一些信息:

内核对子进程终止(SIGCLD)信号的处理方法与其他信号有所区别。当进程检查出收到了一个子进程终止的信号时,缺省情况下,该进程 就象没有收到该信号似的,如果父进程执行了系统调用wait,进程将从系统调用wait中醒来并返回wait调用,执行一系列wait调用的后续操作(找 出僵死的子进程,释放子进程的进程表项),然后从wait中返回。SIGCLD信号的作用是唤醒一个睡眠在可被中断优先级上的进程。如果该进程捕捉了这个 信号,就象普通信号处理一样转到处理例程。如果进程忽略该信号,那么系统调用wait的动作就有所不同,因为SIGCLD的作用仅仅是唤醒一个睡眠在可被 中断优先级上的进程,那么执行wait调用的父进程被唤醒继续执行wait调用的后续操作,然后等待其他的子进程。 

如果一个进程调用signal系统调用,并设置了SIGCLD的处理方法,并且该进程有子进程处于僵死状态,则内核将向该进程发一个SIGCLD信号。

总结如下:

当父进程阻塞在wait系统调用,子进程结束的时候,内核发送SIGCHLD到进程,父进程从wait调用中醒来,继续执行wait的后续操作(释放僵尸子进程),切换到用户态后,进程执行信号处理函数,此时waitpid已经取不到僵死子进程的信息,所以while里面的语句没有执行。

如果在调试的时候,把断点设置SIGCHLD信号处理函数的while之前,会发现,执行到断点的时候,ps一下,发现根本就没了僵尸进程了。

声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
  • 上一篇:没有了
  • 下一篇:没有了
未上传头像