10.7 SIGCHLD定义
经常混淆的两个信号就是SIGCLD以及SIGCHLD,信号SIGCLD源于System V,该信号的含义与源自BSD的信号SIGCHLD不一致。同时POSIX.1信号也称为SIGCHLD.源自BSD的信号SIGCHLD的语义比较正常,当该信号出现的时候,表示子进程的状态发生了变化,然后我们需要调用一个wait函数来查看究竟发生了什么。
System V对于SIGCLD的处理历史以来都与其他信号不同,基于SVR4i的系统保持了这个有问题的传统,如果我们使用函数signal或者是sigset(SVR3中用于设置信号处理函数的函数)设置信号的处理函数,SIGCLD早期的处理包含如下行为:
- 如果将信号处理函数指定为SIG_IGN,调用进程的子进程将永远不会产生僵尸进程。注意这与该信号的默认处理时不同的,在图10.1中提到其默认处理时忽略。取而代之的是,当子进程终止的时候,子进程的状态将被抛弃,如果其父进程接着调用其中一个wait函数,调用进程将被阻塞直到所有子进程终止,然后wait函数返回-1,并且errno被设置为ECHILD.(注意:信号的默认处理时忽略信号,但是该默认处理方式并不会产生上述行为,而是我们必须将该信号的处理函数设置为SIG_IGN.)
POSIX.1并没有指定当SIGCHLD被忽略的时候会发生什么,所以上述处理也是被允许的,而XSI选项要求这一处理被信号SIGCHLD支持。
4.4BSD在SIGCHLD被忽略的时候总是生成僵尸进程,如果我们想要避免僵尸进程的产生,我们必须wait所有的子进程,在SVR4中,只要调用signal或者是sigset中的一个将SIGCHLD的处理函数设置为SIG_IGN,僵尸进程就永远不会产生,本书中描述的4个平台都与SVR4的相同。
使用函数sigaction而言,我们可以设置SA_NOCLDWAIT标志来避免僵尸进程,该行为对于本书中介绍的4个平台都是支持的。 - 如果我们设置SIGCLD的处理函数,内核就会立即检查是否有子进程处于等待处理的情况,若有,则立即调用SIGCLD函数。
上述第二项改变了我们编写信号处理函数的方式,正如下面的例子中将会讲到的一样.
Example
在10.4节中提到,在信号处理函数中的第一件事就是再次调用signal函数,这样处理时为了最小化信号处理函数被还原为默认处理的时间窗口,图10.6就是按照这一规则进行编写的程序,但是该程序在传统的System V平台上并不能很好地工作,其输出将是连续不断的字符串”SIGCLD received”,最会进程由于堆栈空间溢出而异常终止。
#include "apue.h"
#include <sys/wait.h>
static void sig_cld(int signo);
int main()
{
pid_t pid;
if(signal(SIGCLD, sig_cld) == SIG_ERR)
perror("signal error");
if((pid = fork()) < 0)
{
perror("fork error");
}
else if(pid == 0)
{
/* child process*/
sleep(2);
_exit(0);
}
pause(); /*parent process*/
exit(0);
}
static void sig_cld(int signo)
{
pid_t pid;
int status;
printf("SIGCLD received\n");
if(signal(SIGCLD, sig_cld) == SIG_ERR) /*reestablish handler*/
perror("signal error");
if((pid = wait(&status)) < 0) /*fetch child status*/
perror("wait error");
printf("pid = %d\n", pid);
}
上述程序的问题是:在信号处理函数的开始位置调用了函数signal,这对应于上面讨论的第二项–内核检查是否有子进程需要wait for(在上述程序中符合这一情况,因为我们正在处理SIGCLD信号),所以对于signal函数的调用会产生另一次对于信号处理函数的调用,信号处理函数反过来又会调用signal函数,于是整个进程就会不断地重复运行。
为了解决上述程序的问题,我们必须将对函数signal的调用移动到wait函数之后,通过这样做我们在捕获到子进程的终止状态以后再调用signal函数,该信号仅仅在其他子进程终止的时候才会再次产生。
POSIX.1声明:在我们建立SIGCHLD的信号处理函数的时候,如果已经存在一个还没有被wait的终止的子进程,信号是否需要生成并没有指定,因此上述情况是允许的,但是对于POSIX.1而言,在信号产生以后并不会复位信号处理函数为默认函数(假设我们正在使用的是POSIX.1的sigaction函数来设置信号处理函数),便没有需要在信号处理函数中再次调用函数signal了。于是上述问题就消失了。
转载于:https://www.cnblogs.com/U201013687/p/5518345.html
10.7 SIGCHLD定义相关推荐
- Go 学习笔记(10)— 数组定义、数组声明、数组初始化、访问数组、数组相等、向函数传递数组
1. 数组定义 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形.字符串或者自定义类型. 2. 声明数组 Go 语言数组声明需要指定元素类型及元素个数,语 ...
- 习题10.3 分别定义Teacher类和Cadre类,采用多重继承方式由这两个类派生出新类Teacher_Cadre类。
分别定义Teacher(教师)类和Cadre(干部)类,采用多重继承方式由这两个类派生出新类Teacher_Cadre(教师兼干部)类.要求: ① 在两个基类中都包含姓名.年龄.性别等数据成员. ② ...
- react学习(10)----react数组定义 从0开始 直接加个0下标空
{title: '状态',dataIndex: 'status',render: (text, row) => {let arr = ['', '未开始', '进行中', '已结束', '已作废 ...
- 定义一个时钟类(TimeDemo),属性有:时、分、秒(默认值10时30分),方法有展示当前时间、过1秒,过1分钟,过1小时后的时分秒;在测试类中实现过10秒,过10分,过10小时后的时间展示
题目: 定义一个时钟类(TimeDemo),属性有:时.分.秒(默认值10时30分),方法有展示当前时间.过1秒,过1分钟,过1小时后的时分秒:定义成员方法分别对时.分.秒进行加减运算,保证运算后时间 ...
- ADPRL - 近似动态规划和强化学习 - Note 10 - 蒙特卡洛法和时序差分学习及其实例 (Monte Carlo and Temporal Difference)
Note 10 蒙特卡洛法和时序差分学习 Monte Carlo and Temporal Difference 蒙特卡洛法和时序差分学习 Note 10 蒙特卡洛法和时序差分学习 Monte Car ...
- c语言宏定义_掌握C语言,中文编程不是梦
文/Edward 前面我们在讲节程序编译的时候,编译器做的第一步就是预处理.C语言的预处理,其实是编译器在对整个工程编译之前做的一些文本性质的工作,例如我们经常使用的#include,这就是一个典型的 ...
- int * * a[10] int * (*a)[10]和 int(*a[10])() 是什么意思
int* (*a)[10]; a是一个指向包含10个int型指针元素的数组. 比如: #include <stdio.h>int main() {// 定义数组,包含10个int*int* ...
- Oracle编程入门经典 第10章 PLSQL
目录 10.1 总览... 1 10.2 基于程序块的开发... 1 试验:PL/SQL程序块... 2 工作原理... 2 块嵌套... 2 10.3 ...
- 【机器学习入门笔记7:TensorFlow常量变量的定义】20190210
2019-02-10 by 崔斐然 学习过程: #基础语法 #API调用 #原理 #高级语言一般都有基础数据类型 运算符 流程 字典 数组 元组 import tensorflow as ...
最新文章
- docker 命令详细解释
- 丁克是什么意思,丁克家庭是什么意思,丁克家庭为什么越来越多
- odbc mysql导出access_将mysql数据导入access数据库
- spring使用 hibernate jpa JpaRepository
- 【java】打印一个对象即打印出该对象toString()返回值
- lte基站可以做ntp server吗?_你手机信号强吗?学会这几招快速提升你的手机信号...
- wind金融数据接口python_Wind量化接口
- linux su 拒绝权限,Linux禁止非WHEEL用户使用su命令
- 彻底弄明白Gradle相关配置
- Vultr与阿里云结合自动换IP的解决方案
- python模拟登录163邮箱_python模拟登陆163邮箱并获取通讯录 | 学步园
- Unity3D学习 ③ 摄像机视角跟随
- 字符串和转义字符的知识和应用
- 【Android开发日记】jsonObject = new JSONObject(info)报错 A JSONObject text must begin with '{' at character
- 用Photoshop制作LOMO风格暗角效果照片
- jquery mouse事件小坑
- 给定n个整数,请统计出每个整数出现的次数,按出现次数从多到少的顺序输出。
- 如何自定义百度云常用服务器,经验分享:如何将百度云做成网站文件服务器
- [生存志] 第53节 晏子春秋录纯臣
- java个性签名_程序员用搞笑个性签名
热门文章
- 锐捷深入油田场景 助力胜利油田生产物联网通向“新胜利”之路
- android类京东到家开发源码
- matlab中surf怎么改变颜色_MATLAB作图
- c++ - 第1节 - c++入门
- 《流浪地球2》数字生命与我们的距离
- 准!武汉大学和高德组队 拿下国际顶赛“车载环境下的手机定位”组别冠军
- Ribbon负载均衡策略、懒加载及饥饿加载
- win10必须禁用的服务_Windows Event Log服务能否关闭?Win10系统Event Log服务详解
- 手机备忘录怎么将图片转文字
- java实现基于AmazonS3文件上传、下载、删除操作