进程捕捉到信号对其进行处理时,进程正在执行的正常序列就被信号处理程序临时中断,它首先执行该信号处理程序中的指令。如果从信号处理程序返回(例如没有调用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. React 零碎笔记

    1.对数组的操作(添加.更新.删除) const posts = [...this.state.posts]; posts.push(post); this.setState({posts}); =& ...

  2. 0、Python学习路线

    阶段一.Python语言(熟练掌握Python多线程并发编程技术,可以编写爬虫程序和语音识别软件.) 1.1 基础语法 1.1.1 python概述     1.1.2 数据的存储     1.1.3 ...

  3. WebForm FindControl的使用方法

    Control.FindControl (String):在当前的命名容器中搜索带指定 id参数的服务器控件. 有点类似javascript中的getElementById(string); 简单的例 ...

  4. codeforces#571Div2 D---Vus the Cossack and Numbers【贪心】

    题目:http://codeforces.com/contest/1186/problem/D 题意:给定一个大小为$n$的浮点序列,这$n$个数的和为0. 现在对这个序列中的每个数,进行向上取整或向 ...

  5. 使用开发IDE生成一个springboot工程。

    说实话,没办法,大势所趋. 当今天下,大企业,还是小公司,只要有想要更高效率的提高开发效率,能频繁迭代,又影响最小,那么只有使用分布式工程开发. 使用它就因为他快,加载东西,插件快,jar包引入方便. ...

  6. 53、servlet3.0-简介&测试

    53.servlet3.0-简介&测试 Servlet 4.0 : https://www.jcp.org/en/jsr/summary?id=servlet+4.0

  7. Mysql查看所有表的数据量

    ##查看所有表信息 SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'pcms-zgh20190327' ##查看各个表数据量 ...

  8. LOJ P10116 清点人数 题解

    每日一题 day13 打卡 Analysis 用简单的树状数组维护单点修改和查询就行了 #include<iostream> #include<cstdio> #include ...

  9. learning scala for comprehensions

    code: package com.aura.scala.day01 object forComprehensions { def main(args: Array[String]): Unit = ...

  10. 模拟I2C协议学习点滴之原理框架

    I2C是一种串行总线协议. 目前几种常用的串行总线有UART.SPI和I2C协议.UART协议的总线只有两条,发送(Transmit:TX)和接收(Receive:RX),没有时钟信号,这就要求两位数 ...