【摘自《Linux/Unix系统编程手册》】

Unix系统提供了两种方式来改变信号处置:signal() 和 sigaction()。

signal() 的行为在不同Unix实现间存在差异,这也意味着对可移植性有所追求的程序绝不能使用此调用来建立信号处理函数。故此,sigaction() 是建立信号处理器的首选API(强力推荐)。

信号处理器

信号处理器程序(也称为信号捕捉器)是当指定信号传递给进程时将会调用的一个函数。

调用信号处理器程序,可能会随时打断主程序流程。内核代表进程来调用处理器程序,当处理器返回时,主程序会在处理器打断的位置恢复执行。

signal()

#include <signal.h>
void ( *signal(int sig, void (*handler)(int)) ) (int);
Returns previous signal disposition on success, or SIG_ERR on error

针对信号处理器函数指针做如下类型定义,有助于理解:

typedef void (*sighandler_t)(int);

signal() 原型可以改写为:

sighandler_t signal(int sig, sighandler_t handler);

在为 signal() 指定handler参数时,可以以如下值来代替函数地址:

SIG_DFL
将信号处置重置为默认值。这适用于将之前signal()调用所改变的信号处置还原
SIG_IGN
忽略该信号。如果信号专为此进程而生,那么内核会默默将其丢弃。进程甚至从未知道曾经产生了该信号

调用 signal() 成功将返回先前的信号处置,有可能是先前安装的处理器函数地址,也可能是常量 SIG_DFL  和 SIG_IGN 之一。如果调用失败,将返回 SIG_ERR。

示例:

 #include <signal.h>
#include "tlpi_hdr.h" static void sigHandler(int sig)
{
static int count = ;
/* UNSAFE: This handler uses non-async-signal-safe functions (printf(), eixt())*/ if (sig == SIGINT) {
count++;
printf("Caught SIGINT (%d)\n", count);
return; /* Resume execution at point of interruption*/
} /* Must be SIGQUIT - print a message and terminate the process*/ printf("Caught SIGQUIT - that's all forks!\n");
exit(EXIT_SUCCESS);
} int main(int argc, char* argv[])
{
if (signal(SIGINT, sigHandler) == SIG_ERR) {
errExit("signal");
}
if (signal(SIGQUIT, sigHandler) == SIG_ERR) {
errExit("signal");
} for (;;)
pause();
}

sigaction()

#include <signal.h>
int sigaction(int sig, const struct sigaction* act, struct sigaction* oldact);
Returns on success, or - on error

sig参数标识想要获取或改变的信号编号。该参数可以是除去SIGKILL和SIGSTOP之外的任何信号。

act参数是一枚指针,指向描述信号新处理器的数据结构,如果仅对现有处理器感兴趣,可以指定act为NULL。oldact指向当前的处理器,若无意获取此信息,可以指定为NULL。

struct sigaction
{
union
{
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
} _sigaction_handler;
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
/* Following defines make the union fields look like simple fields in the parent structure*/
#define sa_handler __sigaction_handler.sa_handler
#define sa_sigaction __sigaction_handler.sa_sigaction

sa_handler字段对应于signal()的handler参数。其所指定的值为信号处理器函数的地址,亦或是常量SIG_IGN、SIG_DFL之一。仅当sa_handler是信号处理程序的地址时,即sa_handler的取值在SIG_IGN和SIG_DFL之外,才会对sa_mask和sa_flags字段加以处理,余下的字段sa_restorer,不适用于应用程序。

注:

sa_restorer字段仅供内部使用,用以确保当信号处理器程序完成后,会去调用专用的sigreturn() 系统调用,借此来恢复进程的执行上下文,以便进程从信号处理器中断的位置继续执行。

sa_mask字段定义了一组信号,在调用有sa_handler所定义的处理器程序时将阻塞改组信号。当调用信号处理器程序时,会在调用信号处理器之前,将该组信号中当前未处于进程掩码之列的任何信号自动添加到进程掩码中。这些信号将保留在进程掩码中,直至信号处理器函数返回,届时将自动删除这些信号。利用sa_mask字段可指定一组信号,不允许它们中断此处理器程序的执行。此外,引发对处理器程序调用的信号将自动添加到进程信号掩码中。这意味着,当正在执行处理器程序时,如果同一信号实例第二次抵达,信号处理器程序将不会递归中断自己。由于不会对遭阻塞的信号进行排队处理,如果在处理器程序执行中重复产生这些信号中的任何信号,(稍后)对信号的传递都是一次性的。

sa_flags字段是一个位掩码,指定用于控制信号处理过程的各种选项。该字段包含的位如下(可以相或(|))

signal() 和 sigaction()的更多相关文章

  1. Linux进程间通信(一): 信号 signal()、sigaction()

    一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...

  2. Linux 信号:signal 与 sigaction

    0.Linux下查看支持的信号列表: france@Ubuntux64:~$ kill -l ) SIGHUP ) SIGINT ) SIGQUIT ) SIGILL ) SIGTRAP ) SIGA ...

  3. 信号处理signal、sigaction、pause、信号嵌套处理、不可重入函数

    信号的捕捉和处理 主要由signal和sigaction函数来完成.还有一个函数pause,它可用来响应任何信号,不过不做任何处理. 1.signal函数 typedef void (*sighand ...

  4. linux c 之signal 和sigaction区别

    http://blog.csdn.net/muge0913/article/details/7331129 要对一个信号进行处理,就需要给出此信号发生时系统所调用的处理函数.可以对一个特定的信号(除去 ...

  5. linux 信号signal和sigaction理解

    今天看到unp时发现之前对signal到理解实在浅显,今天拿来单独学习讨论下. signal,此函数相对简单一些,给定一个信号,给出信号处理函数则可,当然,函数简单,其功能也相对简单许多,简单给出个函 ...

  6. signal和sigaction 分析

    1:signal 函数 原型: sighandler_t signal(int signum, sighandler_t handler)      typedef void (*sighandler ...

  7. APUE学习笔记——10信号——信号接口函数 signal 和 sigaction

    signal函数     signal函数是早起Unix系统的信号接口,早期系统中提供不可靠的信号机制.在后来的分支中,部分系统使用原来的不可靠机制定义signal函数,如 Solaris 10 .而 ...

  8. signal函数、sigaction函数及信号集(sigemptyset,sigaddset)操作函数

    信号是与一定的进程相联系的.也就是说,一个进程可以决定在进程中对哪些信号进行什 么样的处理.例如,一个进程可以忽略某些信号而只处理其他一些信号:另外,一个进程还可以选择如何处理信号.总之,这些总与特定 ...

  9. 信号处理篇alarm ferror kill mkfifo pause pclose perror pipe popen sigaction sigaddset sigdelset sigemptyset signal sleep strerror

    alarm(设置信号传送闹钟) 相关函数 signal,sleep 表头文件 #include<unistd.h> 定义函数 unsigned int alarm(unsigned int ...

随机推荐

  1. Linux内核之内存管理

    Linux内核之内存管理 Linux利用的是分段+分页单元把逻辑地址转换为物理地址; RAM的某些部分永久地分配给内核, 并用来存放内核代码以及静态内核数据结构; RAM的其余部分称动态内存(dyna ...

  2. [C]*和&

    一 .& c的&被称为“寻址运算符”,作用是指向某变量的指针: 请看以下代码: int main(void){ int int_1 = 16;        printf(" ...

  3. Python 队列

    import multiprocessing import time if __name__ == '__main__': # 创建消息队列 # 3: 表示消息队列最大个数 queue = multi ...

  4. jQuery实现鼠标点击div外的地方div隐藏消失的效果(转)

    转:https://www.cnblogs.com/jsingleegg/p/3456152.html css部分: <style type="text/css">.p ...

  5. Swift 学习- 09 -- 枚举

    // 递归枚举 // 美家居为一组相关的值定义了一个共同的类型, 使你可以在代码中以类型安全的的方式使用这些值. // 如果你熟悉C语言, 你会知道在C语言中, 枚举会为一组整型值分配相关联的名称, ...

  6. Oracle 所有字典

    select * from DBA_CONS_COLUMNS ; ---Information about accessible columns in constraint definitions s ...

  7. Oracle 查询优化的基本准则详解

      注:报文来源:想跌破记忆寻找你 < Oracle 查询优化的基本准则详解 > Oracle 查询优化的基本准则详解 1:在进行多表关联时,多用 Where 语句把单个表的结果集最小化, ...

  8. Confluence 6 配置默认语言界面

    Confluence 6 配置默认语言使用的界面. https://www.cwiki.us/display/CONFLUENCEWIKI/Choosing+a+Default+Language

  9. vue this触发事件

    @click="aHref(index,$event)" aHref: function(url,event){ this.$router.push(url); $(event.c ...

  10. 使用 Kafka 和 Spark Streaming 构建实时数据处理系统

    使用 Kafka 和 Spark Streaming 构建实时数据处理系统 来源:https://www.ibm.com/developerworks,这篇文章转载自微信里文章,正好解决了我项目中的技 ...