信号(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. springBoot @EnableAutoConfiguration深入分析

    1.新建一个项目中需要提供配置类 2.在META-INF/spring.factorties在文件中配置 org.springframework.boot.autoconfigure.EnableAu ...

  2. C++基础知识(一)

    C++中头文件中class的两个花括号后面要加上分号,否则会出现很多的莫名奇妙的错误. 一. 每一个C++程序(或者由多个源文件组成的C++项目)都必须包含且只有一个main()函数.对于预处理指令, ...

  3. Python替换字符串中的反斜杠\

    s = 'cdp\nd' result = eval(repr(s).replace('\\', '@')) print(result) repr() 函数可以将字符串转换为python的原始字符串( ...

  4. [HNOI2008]GT考试 矩阵优化DP

    ---题面--- 题解: 一开始看觉得很难,理解了之后其实还挺容易的. 首先我们考虑朴素DP: 令f[i][j]表示长串到了第i项, 与不吉利数字(模式串)匹配到了第j项的方案. 显然ans = f[ ...

  5. UVA.11636 Hello World! (思维题)

    UVA.11636 Hello World! (思维题) 题意分析 这题挺水的,还是错了几发. QWQ. 有一个同学打了一行hello world,现在他想打n行hello world,请问最少复制粘 ...

  6. NOIP2017 列队——平衡树

    平衡树蒟蒻,敲了半天. 其实思路很简单,就是把许多个人合并成一个区间.必要的时候再拆开.(是不是和这个题的动态开点线段树有异曲同工之妙?) 每次操作最多多出来6个点. 理论上时间复杂度是nlogn,空 ...

  7. [CQOI2011]放棋子

    想到了50%吧算是. f[i][j][k]表示,前i种,占了j行k列.方案数. 发现,转移要处理:“用c个棋子,占据n行m列”的方案数. 设g[i][j][k]表示,i行j列用k个棋子占的方案数.直接 ...

  8. MySQL5.7 添加、删除用户与授权

    mysql -uroot -proot 例子: 创建用户mysql> CREATE USER 'xiaoyaoji'@'%' IDENTIFIED BY 'xiaoyaoji';Query OK ...

  9. 背景建模技术(六):帧处理(FrameProcessor)模块

    前面几篇文章简单介绍了BgsLibrary的入口函数.视频分析和视频捕获模块,本文将简单介绍帧处理模块,即对每一帧进行处理的函数,也就是真正调用背景建模算法的接口处. 下面贴出源码供大家分析: #in ...

  10. POJ1904:King's Quest(强连通+思维)

    King's Quest Time Limit: 15000MS   Memory Limit: 65536K Total Submissions: 10352   Accepted: 3815 题目 ...