信号(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. 浅析Docker容器的应用场景

    本文来自网易云社区 作者:娄超 过去几年开源界以openstack为代表的云计算持续火了好久,这两年突然又冒出一个叫Docker的容器技术,其发展之迅猛远超预料.网上介绍Docker容器的文章已经很多 ...

  2. CCS3 动画-鼠标放上去放大背景图片

    ---〉 效果如上,一个简单的过渡放大效果, <!DOCTYPE HTML> <html> <body> <style> #test{ width:30 ...

  3. 【Python】python-内置常量

    引言 Python的内置常量不多,只有6个,分别是True.False.None.NotImplemented.Ellipsis.__debug__ 一.True 1.True是bool类型用来表示的 ...

  4. 推荐算法相关总结表(包括DM)

    推荐算法总结表 表1 推荐算法分类 个性化推荐算法分类 启发式算法 基于模型 基于内容 TF-IDF 聚类 最大熵 相似度度量 贝叶斯分类 决策树 神经网络 专家系统 知识推理 协同过滤 K近邻 聚类 ...

  5. 【刷题】BZOJ 2882 工艺

    Description 小敏和小燕是一对好朋友. 他们正在玩一种神奇的游戏,叫Minecraft. 他们现在要做一个由方块构成的长条工艺品.但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工 ...

  6. [Leetcode] valid sudoku 有效数独

    Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be ...

  7. HDU 5651 逆元

    xiaoxin juju needs help Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/ ...

  8. HDU 2646 栈的应用 STL

    Expression Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  9. Android提示框与通知的使用

    1.通知 Android 3.0以前使用的方法 NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION ...

  10. bzoj 4414 数量积 结论题

    数量积 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 389  Solved: 147[Submit][Status][Discuss] Descri ...