信号(signal)机制是UNIX系统中最为古老的进程之间的通信机制,它用在一个或多个进程之间传递异步信号,信号可以由各种异步事件产生,如:

键盘中断等等,在Linux 的shell 中,也可以使用信号将作业控制命令传递给它的子进程。在linux系统中,定义了一系列的信号,这些信号可以由

内核产生,也可以有系统中的其他进程产生,只要这些进程的权限足够大。进程可以屏蔽掉大多数的信号,除了SIGSTOP和SIGKILL,前者使一个

正在运行的进程暂停,后者则使一个正在运行的进程退出。应用程序收到信号后,有三种处理方式:忽略,默认,或捕捉。进程收到一个信号后,

会检查对该信号的处理机制。如果是SIG_IGN,就忽略该信号;如果是SIG_DFT,则会采用系统默认的处理动作,通常是终止进程或忽略该信号;

如果给该信号指定了一个处理函数(捕捉),则会中断当前进程正在执行的任务,转而去执行该信号的处理函数,返回后再继续执行被中断的任务。

1.信号截取函数 signal()

#include<signal.h>
typedef void (*sighandler_t) (int);
sighandler_t signal(int signum, sighandler_t handler);
signal()是最简单的给进程安装信号处理器的函数,第一个参数指定信号,第二个参数为该信号指定一个处理函数。它的返回值为原信号处理函数,
或SIG_ERR
 
2.发送信号的kill和raise函数
 
#include<sys/types.h>
#include<signal.h> 
int kill(pid_t pid, int sig);
int raise(int sig);
kill()发送信号给指定进程,raise()发送信号给进程本身。对kill()的pid,有如下描述:
 
pid > 0 将信号发送给ID为pid的进程
pid == 0 将信号发送给与发送进程属于同意个进程组的所有进程
pid < 0 将信号发送给进程组ID等于pid绝对值的所有进程
pid == -1 将信号发送给该进程有权限发送的系统里的所有进程
 
3.等待信号的pause函数
int pause(void);
 
pause()会使当前进程挂起,直到捕捉到一个信号,对指定为忽略的信号,pause()不会返回。只有执行了一个信号处理函数,并从其返回,
puase()才返回-1,并将errno设为EINTR。
 
4.信号集函数
 
int sigemptyset(sigset_t * set);
int sigfillset(sigset_t * set);
int sigaddset(sigset_t * set, int signum);
int sigdelset(sigset_t * set, int signum);
int sigismember(sigset_t * set, int signum);
 
信号集是Linux中的一种特殊的数据类型,由于无法确定信号的多少,所以不能用简单数据类型来包含所有可能的信号,所以系统就定义了一个sigset_t
的数据类型专门用于信号集。同时还定义了一族用于处理信号集的函数。这样用户可以不必关心信号集的实现,只要使用以上这组函数来处理信号集就可以了。
 sigemptyset()和sigfillset()都用于初始化一个信号集,前者用于清空信号集中所有的信号,后者则用于设置信号集中所有的信号;信号集在使用前必须要经
过初始化,初始化后,就可以用sigaddset()和sigdelset()往信号集里添加删除信号了。sigismember()用于判断指定信号是否在信号集中。
 
5.修改信号屏蔽字的sigprocmask函数

 
int sigprocmask(int how, const sigset_t * set, sigset_t * oldset);
 
每个进程都会有一个信号屏蔽字,它规定了当前进程要阻塞的信号集。对于每种可能的信号,信号屏蔽字中都会有一位与之对应,如果该位被设置,该信号当前
就是阻塞的。进程可以通过sigprocmask()来获得和修改当前进程的信号屏蔽字。sigpromask()根据how指定的方式,设置进程的当前信号屏蔽字为set,并将
旧的信号屏蔽字保存在oldset中返回。如果set为NULL,则不修改当前信号屏蔽字,而将其通过oldset返回;如果oldset为NULL,则不会返回旧的信号屏蔽字。
how支持以下三种方式,见下表。
 
 how  说明

SIG_BLOCK

SIG_UNBLOCK

SIG_SETMASK

设置阻塞set指定的信号集

设置解除阻塞set指定的信号集

设置当前信号屏蔽字为set,在set中的信号都会被阻塞,不在set中的信号会被递送

6.获得未决的信号sigpending

int sigpending(sigset_t * set);
 
信号是由某些事件产生的,这些事件可能是硬件异常(如被零除),软件条件(如计时器超时),终端信号或调用kill()/raise()函数。信号产生时,内核通常会在进程表中
设置某种标志,表示当前信号的状态。当内核对信号采取某种动作时,我们说向进程递送(deliver)了一个信号,而在信号产生和递送之间的间隔内,该信号的状态是
未决的(pending)。 而sigpending函数在set中返回进程中当前尚未递送的信号集。
 
7.查询或设置信号处理方式的sigaction()函数

int sigaction(int signo,const struct sigaction *restrict act,struct sigaction *restrict oact);

sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)。
 

结构sigaction定义如下:

struct sigaction{
  void (*sa_handler)(int);
  sigset_t sa_mask;
  int sa_flag;
  void (*sa_sigaction)(int,siginfo_t *,void *);
};

sa_handler字段包含一个信号捕捉函数的地址

sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加进进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。

sa_flag是一个选项,主要理解两个

SA_INTERRUPT 由此信号中断的系统调用不会自动重启
SA_RESTART 由此信号中断的系统调用会自动重启

SA_SIGINFO 提供附加信息,一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针

SA_INTERRUPT 由此信号中断的系统调用不会自动重启
SA_RESTART 由此信号中断的系统调用会自动重启

SA_SIGINFO 提供附加信息,一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针

最后一个参数是一个替代的信号处理程序

linux编程之信号的更多相关文章

  1. linux系统编程之信号(二):信号处理流程(产生、注册、注销、执行)

        对于一个完整的信号生命周期(从信号发送到相应的处理函数执行完毕)来说,可以分为三个阶段: 信号诞生 信号在进程中注册 信号在进程中的注销 信号处理函数执行 1    信号诞生     信号事件 ...

  2. linux系统编程之信号(一):中断与信号

    一,什么是中断? 1.中断的基本概念 中断是指计算机在执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序,待处理完毕后又返回原来被 ...

  3. linux系统编程之信号(二)

    经过了漫长的间歇,对于c语言的学习也被中断了很久,现实确实有很多的无耐,计划中的事情总会被打乱,但不管怎样,学习的道路是不能休止的,所以经过了一断温习后现在继续学习C语言,话不多说,进入正题: 信号分 ...

  4. 牛人整理分享的面试知识:操作系统、计算机网络、设计模式、Linux编程,数据结构总结 转载

    基础篇:操作系统.计算机网络.设计模式 一:操作系统 1. 进程的有哪几种状态,状态转换图,及导致转换的事件. 2. 进程与线程的区别. 3. 进程通信的几种方式. 4. 线程同步几种方式.(一定要会 ...

  5. 【转】牛人整理分享的面试知识:操作系统、计算机网络、设计模式、Linux编程,数据结构总结

    基础篇:操作系统.计算机网络.设计模式 一:操作系统 1. 进程的有哪几种状态,状态转换图,及导致转换的事件. 2. 进程与线程的区别. 3. 进程通信的几种方式. 4. 线程同步几种方式.(一定要会 ...

  6. 面试知识:操作系统、计算机网络、设计模式、Linux编程,数据结构总结

    基础篇:操作系统.计算机网络.设计模式 一:操作系统 1. 进程的有哪几种状态,状态转换图,及导致转换的事件. 2. 进程与线程的区别. 3. 进程通信的几种方式. 4. 线程同步几种方式.(一定要会 ...

  7. 【转】[IT综合面试]牛人整理分享的面试知识:操作系统、计算机网络、设计模式、Linux编程,数据结构总结

    感谢IT面试群 S-北京-陈磊 的整理分享.   基础篇:操作系统.计算机网络.设计模式         提高篇:WIN32.MFC与Linux 算法篇:算法与数据结构           一:操作系 ...

  8. [转]Linux进程间通信——使用信号

    转载于:http://blog.csdn.net/ljianhui/article/details/10128731         经典!!! Linux进程间通信——使用信号 一.什么是信号 用过 ...

  9. Linux 编程中的API函数和系统调用的关系【转】

    转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...

随机推荐

  1. C结构体【转】

    “结构”是一种构造类型,它是由若干“成员”组成的.每一个成员可以是一个基本数据类型或者又是一个构造类型.结构既是一种“构造”而成的数据类型,那么在说明和使用之前必须先定义它,也就是构造它.如同在说明和 ...

  2. mac终端命令-----常规操作

    OSX 的文件系统 OSX 采用的Unix文件系统,所有文件都挂在跟目录 / 下面,所以不在要有Windows 下的盘符概念. 你在桌面上看到的硬盘都挂在 /Volumes 下. 比如接上个叫做 US ...

  3. Apple - Hdu5160

    Problem Description We are going to distribute apples to n children. Every child has his/her desired ...

  4. 在@Async注解下RequestContextHolder.getRequestAttributes() 获得null的情况

    我们有的时候会在service层获取request填充一些诸如用户名和IP地址等信息,这个时候如果不想从Controller层传request,可以在service直接使用 HttpServletRe ...

  5. 923c C. Perfect Security

    Trie树. 要求字典序最小,所以由前到后贪心的选择.建一个trie树维护b数列. #include<cstdio> #include<algorithm> #include& ...

  6. 洛谷 P3332 [ZJOI2013]K大数查询 解题报告

    P3332 [ZJOI2013]K大数查询 题目描述 有\(N\)个位置,\(M\)个操作.操作有两种,每次操作如果是\(\tt{1\ a\ b\ c}\)的形式表示在第\(a\)个位置到第\(b\) ...

  7. POJ.2387 Til the Cows Come Home (SPFA)

    POJ.2387 Til the Cows Come Home (SPFA) 题意分析 首先给出T和N,T代表边的数量,N代表图中点的数量 图中边是双向边,并不清楚是否有重边,我按有重边写的. 直接跑 ...

  8. Rabbitmq----基础使用

    ---------------rabbitmq的基础使用--------------- 查看消息队列信息 在安装好rabbitmq-server之后,启动服务 使用命令rabbitmqctl list ...

  9. ACE的安装

    转载于:http://www.cnblogs.com/TianFang/archive/2006/12/03/580714.html ACE的安装是一件比较麻烦的事情,这里简单的记录了我在VS2005 ...

  10. 牛客326B 背单词

    传送门:https://ac.nowcoder.com/acm/contest/326/B 题意:给你一个n,你需有找有多少个长度从1~n 的单词,满足最长连续元音少于A个并且最长连续辅音长度少于B. ...