Linux -- 信号编程
进程捕捉到信号对其进行处理时,进程正在执行的正常序列就被信号处理程序临时中断,它首先执行该信号处理程序中的指令。如果从信号处理程序返回(例如没有调用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 -- 信号编程的更多相关文章
- Linux信号实践(1) --Linux信号编程概述
中断 中断是系统对于异步事件的响应, 进程执行代码的过程中可以随时被打断,然后去执行异常处理程序; 计算机系统的中断场景:中断源发出中断信号 -> CPU判断中断是否屏蔽屏蔽以及保护现场 -&g ...
- linux系统编程之信号(七)
今天继续学习信号,主要是学习关于时间和定时器相关的函数的使用,关于这个实际上有很多内容,这里先简要进行说明,等之后再慢慢进行相关深入,也主要是为接下来要做的一个综合linux系统编程的例子做准备,好了 ...
- (50)LINUX应用编程和网络编程之五 Linux信号(进程间通信)
信号实现进程间的通信 3.5.1.什么是信号 ...
- Linux 系统编程 学习:03-进程间通信1:Unix IPC(2)信号
Linux 系统编程 学习:03-进程间通信1:Unix IPC(2)信号 背景 上一讲我们介绍了Unix IPC中的2种管道. 回顾一下上一讲的介绍,IPC的方式通常有: Unix IPC包括:管道 ...
- Linux 网络编程的5种IO模型:信号驱动IO模型
Linux 网络编程的5种IO模型:信号驱动IO模型 背景 上一讲 Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 我们讲解了多路复用等方面的知识,以及有关例程. ...
- Linux系统编程(20)——信号基本概念
信号及信号来源 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知 ...
- linux系统编程之信号(一):中断与信号
一,什么是中断? 1.中断的基本概念 中断是指计算机在执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序,待处理完毕后又返回原来被 ...
- Linux系统编程——进程间通信:信号中断处理
什么是信号? 信号是 Linux 进程间通信的最古老的方式.信号是url=474nN303T2Oe2ehYZjkrggeXCaJPDSrmM5Unoh4TTuty4wSgS0nl4-vl43AGMFb ...
- linux系统编程之信号(二)
经过了漫长的间歇,对于c语言的学习也被中断了很久,现实确实有很多的无耐,计划中的事情总会被打乱,但不管怎样,学习的道路是不能休止的,所以经过了一断温习后现在继续学习C语言,话不多说,进入正题: 信号分 ...
随机推荐
- 使用jQuery快速高效制作网页交互特效--初始jQuery
一. jQuery基本概念介绍 1.1 什么是jQuery一个javascript库,把常用方法写到一个js文件中,需要的时候直接调用即可学习jQuery就是学习一些方法 ...
- Linux 查看系统配置参数
原文链接:http://www.cnblogs.com/aric2016/p/10971690.html 查看 cpu信息: cat /proc/cpuinfo 查看内存信息: grep MemTot ...
- 作业调度系统PBS(Torque)的设置
1.修改/var/spool/torque/server_priv/目录下的nodes文件 Node1 np=16 gpus=4 Node2 np=16 gpus=4 ... 其中Node1为计算节点 ...
- sql server 悲观锁和乐观锁的作用
sql server对并发的处理-乐观锁和悲观锁 假如两个线程同时修改数据库同一条记录,就会导致后一条记录覆盖前一条,从而引发一些问题. 例如: 一个售票系统有一个余票数,客户端每调用一次出票方法,余 ...
- html表格按长度换行
<table style="table-layout:fixed; WORD-BREAK: break-all; WORD-WRAP: break-word; width:200px; ...
- 洛谷 P2119 魔法阵 题解
Analysis 这道题也是考试题,我也依然打了个n三次方暴力.正解是先枚举差,再枚举c和d,a和b用乘法原理优化,这样就能大大减少时间. #include<iostream> #incl ...
- iwap:修改菜单树文件
1.添加mysql数据库连接的jar包. 2.
- 将List<E>内对象按照某个字段排序
主要用到java.util的Collections类 Collections.sort(list); 其中,E必须实现Comparable<E>接口
- java Spring定时器 每个季度执行一次
@Scheduled(cron = " 0 00 00 1 4,7,10,1 ?")//每个季度的第一天零点进行统计此注解是每个季度结束后的下一天执行(因为Spring不识别字母( ...
- 在本机上用IO流实现复制粘贴功能
/** * 复制文件夹 * @param sourcePath * @param targetPath * @throws IOException */ public void copyFolder( ...