signal() 和 sigaction()
【摘自《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()的更多相关文章
- Linux进程间通信(一): 信号 signal()、sigaction()
一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...
- Linux 信号:signal 与 sigaction
0.Linux下查看支持的信号列表: france@Ubuntux64:~$ kill -l ) SIGHUP ) SIGINT ) SIGQUIT ) SIGILL ) SIGTRAP ) SIGA ...
- 信号处理signal、sigaction、pause、信号嵌套处理、不可重入函数
信号的捕捉和处理 主要由signal和sigaction函数来完成.还有一个函数pause,它可用来响应任何信号,不过不做任何处理. 1.signal函数 typedef void (*sighand ...
- linux c 之signal 和sigaction区别
http://blog.csdn.net/muge0913/article/details/7331129 要对一个信号进行处理,就需要给出此信号发生时系统所调用的处理函数.可以对一个特定的信号(除去 ...
- linux 信号signal和sigaction理解
今天看到unp时发现之前对signal到理解实在浅显,今天拿来单独学习讨论下. signal,此函数相对简单一些,给定一个信号,给出信号处理函数则可,当然,函数简单,其功能也相对简单许多,简单给出个函 ...
- signal和sigaction 分析
1:signal 函数 原型: sighandler_t signal(int signum, sighandler_t handler) typedef void (*sighandler ...
- APUE学习笔记——10信号——信号接口函数 signal 和 sigaction
signal函数 signal函数是早起Unix系统的信号接口,早期系统中提供不可靠的信号机制.在后来的分支中,部分系统使用原来的不可靠机制定义signal函数,如 Solaris 10 .而 ...
- signal函数、sigaction函数及信号集(sigemptyset,sigaddset)操作函数
信号是与一定的进程相联系的.也就是说,一个进程可以决定在进程中对哪些信号进行什 么样的处理.例如,一个进程可以忽略某些信号而只处理其他一些信号:另外,一个进程还可以选择如何处理信号.总之,这些总与特定 ...
- 信号处理篇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 ...
随机推荐
- C# string.join
String.Join 方法 平常工作中经常用到string.join()方法,在vs 2017用的运行时(System.Runtime, Version=4.2.0.0)中,共有九个(重载)方法. ...
- curl的http上传文件代码
int http_post_file(const char *url, const char *user, const char *pwd, const char *filename){ ass ...
- LOJ 6277-6280 数列分块入门 1-4
数列分块是莫队分块的前置技能,练习一下 1.loj6277 给出一个长为n的数列,以及n个操作,操作涉及区间加法,单点查值. 直接分块+tag即可 #include <bits/stdc++.h ...
- Alpha 冲刺 (3/10)
目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:冲刺3 团队部分 后敬甲(组长) 过去两天完成了哪些任务 文字描述 组织第一次团队编程 继续阅读小程序开发文档 接下来的 ...
- 021_supervise进行管理利器
一.公司的类似ansible的工具也是用supervise管理的 [admin@mjyall-test-1 /service/ansible-oc-agent]$ ps -ef|grep 19070 ...
- C语言 16进制转float
float hex_to_float(uint8_t *data) { float num = 0.0; uint8_t dd[4] = {data[0], data[1], data[2], dat ...
- centos7怎么永久修改hosname
centos7怎么永久修改hosname 其实,一般来说安装好虚拟机之后,一般都会进行修改hostname,之前也是在修改的时候,遇到过问题,但是没有深究,今天在修改的时候,好好研究了一下,之前看到好 ...
- FreeSWITCH voicemail
功能描述:分机不存在时,进行语音留言. 步骤: 1.编译mod_voicemail 模块.默认是已经有编译 2.加载mod_voicemail模块: fs_cli --> reload mo ...
- springcloud-3:required a bean of type 'com.netflix.discovery.DiscoveryClient' that could not be found.
在写客户端程序的时候,总是报'com.netflix.discovery.DiscoveryClient' that could not be found. 原因在于导入了错误的类:com.netfl ...
- VS下载Github的项目引用报错
错误如下 1.添加新的Nuget包源 添加新的源 https://www.nuget.org/api/v2/ 2.还原Nuget包 3.升级Visual Studio到最新 工具-->获取工具和 ...