进程捕捉到信号对其进行处理时,进程正在执行的正常序列就被信号处理程序临时中断,它首先执行该信号处理程序中的指令。如果从信号处理程序返回(例如没有调用exit或longjmp),则继续执行在捕捉到信号时进程正在执行的正常指令序列。

1. 在信号处理程序中,我们要保证调用”异步信号安全”的函数,即可重入的函数

不可重入的函数大多(a)已知它们使用静态数据结构。(b)它们调用malloc或free(c)它们是标准I/O函数

2. 由于每个线程只有一个errno变量,所以信号处理程序可能会修改其原先值。因此,所有信号处理程序应当在函数的起始保存errno,结尾恢复errno

3. 每个进程都有一个信号屏蔽字(signal mask),它规定了当前要阻塞传递送到该进程的信号集

信号集signal set

int sigemptyset(sigset_t *set); //初始化由set指向的信号集,清除其中所有信号

int sigfillset(sigset_t *set);       //初始化由set指向的信号集,使其包括所有信号

所有应用程序在使用信号集前,要对该信号集调用sigemptyset或sigfillset一次。

信号集初始化之后,可在该信号中增删特定的信号。

int sigaddset(sigset_t *set,int signo)

int sigdelset(sigset_t *set,int signo)

进程的信号屏蔽字

int sigprocmask(int how,const sigset_t *restrict set, const sigset_t *restrict oset)

Oset若是非空指针,那么进程的当前信号屏蔽字通过oset返回

How的三种取值决定了如何修改当前信号屏蔽字:

SIG_BLOCK : 向当前信号屏蔽字中添加参数set包含的信号

SIG_UNBLOCK : 把当前信号屏蔽字中参数set包含的信号删去

SIG_SETMASK : 把参数set设为进程的信号屏蔽字。

请注意,sigprocmask仅为单线程进程定义的。处理多线程进程中信号的屏蔽使用另一个函数

执行信号的处理程序称为信号递达,信号从产生到递达之间的状态称为信号未决。被阻塞的信号将保持在未决状态,直到进程解决对此信号的阻塞。

int sigpending(sigset_t *set)

Set返回当前的未决信号

信号处理的范式

static int pipefd[];

int signal_module_init()

{
struct sigaction act; //信号处理程序指定为sig_handler
act.sa_handler = sig_handler; //在进入信号处理程序前,把act.sa_mask信号集加到进程的信号屏蔽字中。调用sigfillset把所有信号加入这个信号集。这表示当进入信号处理程序后,阻塞一切信号
sigfillset(&act.sa_mask) if( > sigaction(SIGINT,&act,) ||
> sigaction(SIGCHLD,&act,) ||
...... ) {
write_log("failed to init signal:sigaction()");
return -;
}
return signal_pipe_init();
} static int signal_pipe_init()
{
if( < pipe(pipefd,O_CLOEXEC|O_NONBLOCK) ){
write_log("failed to init pipe");
return -;
}
return ;
} static void sig_handler(int signo)
{
//定义一个数组,将你注册的每个信号的signo映射成一个唯一的字符
static const char sig_chars[NSIG+] = {
[SIGINT] = 'I',
[SIGCHLD] = 'C',
.....
}; char s;
int saved_errno; //保存当前的errno。每个线程仅有一个errno变量,不应让信号处理程序中的errno影响正常流程中的errno。因此我们需要在信号处理程序的起始存储errno,在末尾恢复errno
saved_errno = errno;
s = sig_chars[signo];
write(pipefd[],&s,sizeof(s));
errno = saved_errno; } //然后在Reactor中监听pipefd[0]. 其回调函数如下:
void got_signal(ev)
{
int res,ret;
char c;
int fd = ev->fd;
for(;;){
//fd是非阻塞的
do {
res = read(fd,&c,);
} while(res == - && errno == EINTR); //pipe中没有可读数据
if(res <= ){
break;
} switch(c){
case 'I':
dosomething1();
break;
case 'C':
dosomething2();
break;
......
}
}
return;
}

Linux -- 信号编程的更多相关文章

  1. Linux信号实践(1) --Linux信号编程概述

    中断 中断是系统对于异步事件的响应, 进程执行代码的过程中可以随时被打断,然后去执行异常处理程序; 计算机系统的中断场景:中断源发出中断信号 -> CPU判断中断是否屏蔽屏蔽以及保护现场 -&g ...

  2. linux系统编程之信号(七)

    今天继续学习信号,主要是学习关于时间和定时器相关的函数的使用,关于这个实际上有很多内容,这里先简要进行说明,等之后再慢慢进行相关深入,也主要是为接下来要做的一个综合linux系统编程的例子做准备,好了 ...

  3. (50)LINUX应用编程和网络编程之五 Linux信号(进程间通信)

                                                                                 信号实现进程间的通信 3.5.1.什么是信号 ...

  4. Linux 系统编程 学习:03-进程间通信1:Unix IPC(2)信号

    Linux 系统编程 学习:03-进程间通信1:Unix IPC(2)信号 背景 上一讲我们介绍了Unix IPC中的2种管道. 回顾一下上一讲的介绍,IPC的方式通常有: Unix IPC包括:管道 ...

  5. Linux 网络编程的5种IO模型:信号驱动IO模型

    Linux 网络编程的5种IO模型:信号驱动IO模型 背景 上一讲 Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 我们讲解了多路复用等方面的知识,以及有关例程. ...

  6. Linux系统编程(20)——信号基本概念

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

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

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

  8. Linux系统编程——进程间通信:信号中断处理

    什么是信号? 信号是 Linux 进程间通信的最古老的方式.信号是url=474nN303T2Oe2ehYZjkrggeXCaJPDSrmM5Unoh4TTuty4wSgS0nl4-vl43AGMFb ...

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

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

随机推荐

  1. 6. kafka序列化和反序列化

    https://blog.csdn.net/weixin_33690963/article/details/91698279 kafka序列化: 生产者在将消息传入kafka之前需要将其序列化成byt ...

  2. SpringBoot自动配置的魔法是怎么实现的

    SpringBoot 最重要的功能就是自动配置,帮我们省去繁琐重复地配置工作.相信用过SpringBoot的人,都会被它简洁的步骤所惊讶.那么 SpringBoot 是如何实现自动配置的呢? 在这之前 ...

  3. matlab(7) Regularized logistic regression : mapFeature(将feature增多) and costFunctionReg

    Regularized logistic regression : mapFeature(将feature增多) and costFunctionReg ex2_reg.m文件中的部分内容 %% == ...

  4. 除了不要 SELECT * ,程序员使用数据库还应知道的11个技巧

    SQL:sum里加条件SELECT SUM( CASE WHEN "V7010" BETWEEN 0 AND 0.1 THEN 1 ELSE 0 END) FROM "C ...

  5. window.frameElement

    地址:MDN web docs 比如有一个iframe的src是xxx.htmframeElement的作用就是在xxx.htm中获得这个引用它的iframe objet这样你就可以在xxx.htm改 ...

  6. 面试官:讲讲mysql表设计要注意啥

    内容时参考一个博主的,内容写的很好,就忍不住拿过来了,如遇到,请见谅 参考连接:https://www.cnblogs.com/rjzheng/p/11174714.html

  7. c++两种字符串赋值方式 并介绍 C语言下遍历目录文件的方式

    c++字符串声明:一种是声明字符数组并赋值,另一种是直接声明string类 #define _CRT_SECURE_NO_WARNINGS #include<iostream> #incl ...

  8. Centos7 安装相关软件

    1.安装 wget : yum -y install wget

  9. MySql存储过程参考

    Mysql(9)---纪录一次实际开发过程中用到的复杂存储过程 为了尽可能的还原当时为什么需要用到存储过程,下面我写了个详细的文档,我们可以从需求文档出发来分析. 有关存储过程之前也写了两篇文章来做铺 ...

  10. Spring动态代理及Spring Bean的生命周期

    数组添加值 public class DiTest { /** * 数组 */ private String [] arrays; /** * List:集合 */ private List<I ...