引言

先看以下两个信号量:

13)SIGPIPE     当管道读端关闭,再往管道写东西,会发出SIGPIPE信号
17)SIGCHLD   子进程退出会向父进程发出SIGCHLD信号,系统默认处理是忽略掉该信号

代码

/*************************************************************************
> File Name: my_fork.c
> Author: KrisChou
> Mail:zhoujx0219@163.com
> Created Time: Mon 25 Aug 2014 10:42:26 AM CST
************************************************************************/ #include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <signal.h>
void handler(int num)
{
pid_t pid ;
printf("sig_num: %d \n", num);
pid = wait(NULL);
printf("wait : %u \n", pid);
}
int main(int argc, char* argv[])
{
int fds[2];// fds[0] r fds[1] w
pipe(fds);
char buf[1024];
signal(SIGPIPE, handler);
signal(SIGCHLD, handler);
if(fork() == 0)
{
close(fds[1]);
while(memset(buf, 0, 1024), read(fds[0], buf, 1024))
{
write(1, buf, strlen(buf));
}
printf("child over ! \n");
exit(0);
}
if(fork() == 0)
{
exit(0);
}
if(fork() == 0)
{
exit(0);
}
close(fds[0]) ;
while(memset(buf, 0, 1024), read(0, buf, 1024))
{
write(fds[1], buf, strlen(buf));
}
//while(1) ;
return 0 ;
}

运行结果如下:

[purple@localhost review]$ ./a.out
sig_num: 17
wait : 15693
sig_num: 17
wait : 15692
hello
hello
world!
world!
child over !

程序运行时,先是两个子进程先后退出,向父进程发送SIGCHLD 信号,接着执行handler函数,回收两个子进程资源。接着程序执行到父进程的while循环,由于read是阻塞函数,在我们没有按下enter或者ctrl+d之前,时间片会在第一个子进程和父进程之间来回切换。如果输入字符按enter,那么也就是父进程将其写入管道,子进程将其从管道中取出,并显示在屏幕上。

如果按ctrl+d,则父进程退出while循环,并且退出程序。此时第一个子进程成为孤儿进程,被init收养,子进程退出时,会向init发送SIGCHLD 信号,由init回收资源。(注意,init很猛的,它本身就已经将SIGCHLD 注册了,其信号处理函数实现了回收资源)

干货

我们之所以将回收子进程资源的wait函数写在信号处理函数中,是因为wait是阻塞函数。如果父进程阻塞了就不能处理自己的工作了。

之前我们已经提过,当子进程终止时,会给父进程发送SIGCHLD信号,虽然该信号的默认处理动作是忽略,但是父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程,当子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程资源即可。

通常情况下服务器是永远不会退出的,因此我们可以在之前的程序中 return 0 前加个while(1),以此来模拟服务器。

注意

如果父进程先于子进程退出,则子进程成为孤儿进程,此时将自动被PID为1的进程(即init)接管。孤儿进程退出后,它的清理工作有祖先进程init自动处理。但在init进程清理子进程之前,它一直消耗系统的资源,所以要尽量避免。

如果子进程先退出,系统不会自动清理掉子进程的环境,而必须由父进程调用wait或waitpid函数来完成清理工作,如果父进程不做清理工作,则已经退出的子进程将成为僵尸进程(defunct),在系统中如果存在的僵尸(zombie)进程过多,将会影响系统的性能,所以必须对僵尸进程进行处理。

Linux信号处理2的更多相关文章

  1. linux 信号处理 五 (示例)

    [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核对于信号的处理流程包括信号的触发/注册/执 ...

  2. linux信号处理相关知识

      因为要处理最近项目中碰上的多个子进程退出信号同时到达,导致程序不当产生core的情况,今天我花了时间看了一些关于linux信号处理的博客. 总结一下:(知识未经实践) linux信号分两种,一种实 ...

  3. linux 信号处理 四

    一.信号生命周期 从信号发送到信号处理函数的执行完毕 对于一个完整的信号生命周期(从信号发送到相应的处理函数执行完毕)来说,可以分为三个重要的阶段,这三个阶段由四个重要事件来刻画:信号诞生:信号在进程 ...

  4. linux 信号处理 六(全)

    一.信号及信号来源 信号本质 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实 ...

  5. linux 信号处理 三 (信号集的使用)

    sigprocmask系统调用 使用条件: 1.有时候不希望在接到信号时就立即停止当前执行,去处理信号,同时也不希望忽略该信号,而是延时一段时间去调用信号处理函数.这种情况是通过阻塞信号实现的. 2. ...

  6. linux 信号处理 一 (基本概念)

    信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念.Linux对信号机制的大致实现方法.如何使用信号,以及有关信号的几个系统调用. 信号机制是进程之间相互传递消息的一种方法,信号全 ...

  7. Linux信号处理编程

    01. 学习目标 了解信号中的基本概念 熟练使用信号相关的函数 了解内核中的阻塞信号集和未决信号集作用 熟悉信号集操作相关函数 熟练使用信号捕捉函数signal 熟练使用信号捕捉函数sigaction ...

  8. linux信号处理时机

    信号号称所谓软中断,事实上,还是没有真正的硬件中断那样能随时改变cpu的执行流 硬件中断之所以能一发生就得到处理是因为处理器在每个指令周期的结尾都会去检查中断,这种粒度是很细的 但是信号的实现只是在进 ...

  9. Linux信号处理

    给进程设置僵尸状态的目的是维护子进程的信息,以便父进程在以后某个时间获取.这些信息包括子进程的进程ID.终止状态以及资源利用信息(CPU时间,内存使用量等等).如果一个进程终止,而该进程有子进程处于僵 ...

  10. linux信号处理及libcurl的坑

    前言:     最近有个项目, 需要访问第三方服务. 该服务是通过http的形式访问的, 为了安全和加密, 对方提供了一个加密用的C/C++库, 用于对参数进行处理.  鉴于此, 选用了C/C++语言 ...

随机推荐

  1. hdu 5142 NPY and FFT

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5142 NPY and FFT Description A boy named NPY is learn ...

  2. PCRE正则库的使用

    使用pcre编写C或C++程序,然后编译. 对于C程序,编译命令为:gcc -I/usr/local/include/pcre -L/usr/local/lib/pcre -lpcre file.c ...

  3. Go时间戳和日期字符串的相互转换

    Go语言中,获取时间戳用time.Now().Unix(),格式化时间用t.Format,解析时间用time.Parse. 看实例代码: package main import ( "fmt ...

  4. scjp考试准备 - 4 - 关于数组

    好吧这道题我丢脸了,竟然做错了. 如下程序的输出结果是: class Alligator{ public static void main(String[] args){ int[]x[] = {{1 ...

  5. 【分享】生成带数据的Insert语句工具(源码)

    这个工具用于导出带数据的Insert语句,方便在不同版本的数据库上导出数据.有人说sql server 2008自带导出带数据的Insert语句(连接)但是我的数据库版本没有这个选项,无奈之下自己简单 ...

  6. java提供了native2ascii工具

    可以使用这个工具,把中文编码称为ascii码 在命令行输入native2ascii 输入中文 得到数据

  7. Android下写一个永远不会被KILL掉的进程/服务

    Android 系统对于内存管理有自己的一套方法,为了保障系统有序稳定的运信,系统内部会自动分配,控制程序的内存使用.当系统觉得当前的资源非常有限的时候,为了保证一些优先级高的程序能运行,就会杀掉一些 ...

  8. Daily Scrum7

    今天我们小组开会内容分为以下部分: part 1: 研讨上一届的项目里积分制度的功能,确定其不足,以及我们可以改进的地方: part 2: 讨论确定我们项目的积分制度的功能目标: part 3:针对用 ...

  9. 软件工程结对开发——返回一个整数数组中最大子数组的和(JAVA)

    题目:返回一个整数数组中最大子数组的和. 要求: 输入一个整型数组,数组里有正数也有负数: 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和: 求所有子数组的和的最大值.要求时间复杂度为 ...

  10. Java令牌生成器

    package Token; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; im ...