sigaction函数的详解

本文详细介绍了sigaction函数的使用方法及与signal函数的区别。通过代码示例展示了如何利用sigaction实现signal函数的功能,并对比了两者在处理信号时的不同行为。
<div>
<span style="font-size: medium;">本文主要参考《unix环境高级编程》</span>
</div>
<div>
<span style="font-size: medium;"></span>
</div>
<div>
<span style="font-size: medium;">sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)。</span>
</div>
<div>
<span style="font-size: medium;"></span>
</div>
<table style="border-collapse: collapse; width: 95%;" border="1" cellspacing="0" cellpadding="0"><tbody><tr>
<td>
<p style="margin: 5px; line-height: 150%;"><span style="font-size: medium;"><code><span style="color: #000000;"><span style="color: #0000ff;">int</span>
<span style="color: #ff0000;">sigaction</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">int</span>
signo<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">const</span>
<span style="color: #0000ff;">struct</span>
<span style="color: #ff0000;">sigaction</span>
<span style="color: #0000cc;">*</span>
restrict act<span style="color: #0000cc;">,</span>
</span>
</code>
</span>
</p>
<p style="margin: 5px; line-height: 150%;"><span style="font-size: medium;"><code><span style="color: #000000;"> <span style="color: #0000ff;">struct</span>
<span style="color: #ff0000;">sigaction</span>
<span style="color: #0000cc;">*</span>
restrict oact<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
</span>
</code>
</span>
</p>
</td>
</tr></tbody></table>
<p><span style="font-size: medium;">结构sigaction定义如下:</span>
</p>
<table style="border-collapse: collapse; width: 95%;" border="1" cellspacing="0" cellpadding="0"><tbody><tr>
<td>
<p style="margin: 5px; line-height: 150%;"><span style="font-size: medium;"><code><span style="color: #000000;"><span style="color: #0000ff;">struct</span>
<span style="color: #ff0000;">sigaction</span>
<span style="color: #0000cc;">{</span>
<br><span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
sa_handler<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br>
sigset_t sa_mask<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
sa_flag<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
sa_sigaction<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">,</span>
siginfo_t <span style="color: #0000cc;">*</span>
<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">*</span>
<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000cc;">}</span>
<span style="color: #0000cc;">;</span>
</span>
</code>
</span>
</p>
</td>
</tr></tbody></table>
<p><span style="font-size: medium;">sa_handler字段包含一个信号捕捉函数的地址</span>
</p>
<p><span style="font-size: medium;">sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加进进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。</span>
</p>
<p><span style="font-size: medium;">sa_flag是一个选项,主要理解两个</span>
</p>
<table style="border-collapse: collapse; width: 95%;" border="1" cellspacing="0" cellpadding="0"><tbody><tr>
<td>
<p style="margin: 5px; line-height: 150%;"><span style="font-size: medium;"><code><span style="color: #000000;">SA_INTERRUPT 由此信号中断的系统调用不会自动重启<br>
SA_RESTART 由此信号中断的系统调用会自动重启</span>
</code>
</span>
</p>
<p style="margin: 5px; line-height: 150%;"><span style="font-size: medium;"><code><span style="color: #000000;">SA_SIGINFO 提供附加信息,一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针</span>
</code>
</span>
</p>
</td>
</tr></tbody></table>
<p><span style="font-size: medium;">最后一个参数是一个替代的信号处理程序,当设置SA_SIGINFO时才会用他,具体有些烦,暂时用不到,不看了。</span>
</p>
<p><span style="font-size: medium;">下面的代码是用sigaction实现signal函数:</span>
</p>
<p><span style="font-size: medium;"></span>
</p>
<p style="margin: 5px; line-height: 150%;"><span style="font-size: medium;"><code><span style="color: #000000;"><span style="color: #0000cc;">#</span>
<span style="color: #ff0000;">include</span>
<span style="color: #ff00ff;">"apue.h"</span>
<br>
Sigfunc <span style="color: #0000cc;">*</span>
<span style="color: #ff0000;">signal</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">int</span>
signo<span style="color: #0000cc;">,</span>
Sigfunc <span style="color: #0000cc;">*</span>
func<span style="color: #0000cc;">)</span>
<br><span style="color: #0000cc;">{</span>
<br><span style="color: #0000ff;">struct</span>
<span style="color: #ff0000;">sigaction</span>
act<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//新的信号关联信息<br></span>
<br><span style="color: #0000ff;">struct</span>
<span style="color: #ff0000;">sigaction</span>
oact<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//老的信号关联信息<br></span>
<br>
act<span style="color: #0000cc;">.</span>
sa_handler <span style="color: #0000cc;">=</span>
func<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//新的信号处理函数<br></span>
<br><span style="color: #ff0000;">sigemptyset</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">&</span>
act<span style="color: #0000cc;">.</span>
sa_mask<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//初始化屏蔽字<br></span>
<br>
act<span style="color: #0000cc;">.</span>
sa_flags <span style="color: #0000cc;">=</span>
0<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//初始化flags<br></span>
<br><span style="color: #0000ff;">if</span>
<span style="color: #0000cc;">(</span>
signo <span style="color: #0000cc;">=</span>
<span style="color: #0000cc;">=</span>
SIGALRM<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">{//不会重启动</span>
<br><span style="color: #0000cc;">#</span>
<span style="color: #ff0000;">ifdef</span>
SA_INTERRUPT<br>
act<span style="color: #0000cc;">.</span>
sa_flags <span style="color: #0000cc;">|</span>
<span style="color: #0000cc;">=</span>
SA_INERRUPT<span style="color: #0000cc;">;</span>
<br><span style="color: #0000cc;">#</span>
<span style="color: #ff0000;">endif</span>
<br><span style="color: #0000cc;">}</span>
<span style="color: #0000ff;">else</span>
<span style="color: #0000cc;">{ //重启动</span>
<br><span style="color: #0000cc;">#</span>
<span style="color: #ff0000;">ifdef</span>
SA_RESTART<br>
act<span style="color: #0000cc;">.</span>
sa_flags <span style="color: #0000cc;">|</span>
<span style="color: #0000cc;">=</span>
SA_RESTART<span style="color: #0000cc;">;</span>
<br><span style="color: #0000cc;">#</span>
<span style="color: #ff0000;">endif</span>
<br><span style="color: #0000cc;">}</span>
<br><span style="color: #0000ff;">if</span>
<span style="color: #0000cc;">(</span>
<span style="color: #ff0000;">sigaction</span>
<span style="color: #0000cc;">(</span>
signo<span style="color: #0000cc;">,</span>
<span style="color: #0000cc;">&</span>
act<span style="color: #0000cc;">,</span>
<span style="color: #0000cc;">&</span>
oact<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;"><</span>
0<span style="color: #0000cc;">)//新老交换</span>
<br><span style="color: #0000ff;">return</span>
<span style="color: #0000cc;">(</span>
<span style="color: #ff0000;">SIG_ERR</span>
<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">return</span>
<span style="color: #0000cc;">(</span>
oact<span style="color: #0000cc;">.</span>
sa_handler<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000cc;">}</span>
</span>
</code>
</span>
</p>
<p style="margin: 5px; line-height: 150%;"><span style="font-size: medium;"><br></span>
</p>
<p style="margin: 5px; line-height: 150%;"><span style="font-size: medium;"><br></span>
</p>
<p style="margin: 5px; line-height: 150%;"><span style="font-size: medium;">于signal 函数和 sigaction 函数的区别<br><br>
注意 : <br>
<1> sigaction <br>
*一般用法:<br>
19<br>
20 phan.sa_handler = &sig_handler;<br>
21 sigemptyset(&phan.sa_mask);<br>
23 phan.sa_flags = 0; 或 //phan.sa_flags = SA_RESTART; 其效果和signal 一样<br>
24 sigaction(SIGALRM, &phan, NULL);<br><br><br><br>
*注意<br><strong>一般不是重启动的函数,除非把sa_flag=SA_RESTART.</strong>
也就是说当信号到来,中断其阻塞的I/O操作,或其他阻塞的操作时,<br>
他们会自动启动这些操作,而不会中断这些操作.而这些I/O操作会保持原来的阻塞状态就好好象根本没有信号到来一样.<br><br>
<2>signal <br><strong> 函数是重启动的,</strong>
当使用该函数安装信号处理函数时,其阻塞的操作将会被中断<br><br>
实际使用例子:<br><br></span>
</p>
<pre class="Csharp"><span style="font-size: medium;">/*<br>
* test for alarm<br>
*/<br>
#include "apue.h"<br>
void sig_handler(int signo);<br>
void sig_handler2(int signo);<br>
void pr_mask(const char *str);<br>
int<br>
main(void)<br>
{<br>
int i;<br>
struct sigaction phan;<br>
char str[100] = {'/0'};<br>
//phan.sa_handler = &sig_handler2;<br>
phan.sa_handler = &sig_handler;<br>
sigemptyset(&phan.sa_mask);<br>
//phan.sa_flags = SA_RESTART; //如果使用这一行,将会阻塞在read函数<br>
phan.sa_flags = 0;<br>
sigaction(SIGALRM, &phan, NULL);<br>
//signal(SIGALRM, sig_handler2);<br>
for(i=0;;i++){<br>
alarm(3);<br>
fprintf(stderr, "do something/n");<br>
read(STDIN_FILENO, str, sizeof(str));<br>
fprintf(stderr, "[%d] done/n", i);<br>
//alarm(0);<br>
//pause();<br>
}<br>
return(0);<br>
}<br>
void sig_handler(int signo)<br>
{<br>
struct sigaction phan;<br>
switch(signo){<br>
case SIGALRM: <br>
//如果下面的函数将会阻塞在read函数.因为它会让阻塞的操作自动重启动 <br>
//signal(SIGALRM, sig_handler);<br>
phan.sa_handler = &sig_handler;<br>
sigemptyset(&phan.sa_mask);<br>
phan.sa_flags = 0;<br>
sigaction(SIGALRM, &phan, NULL);<br>
pr_mask("sig_handler : "); //打印出信号掩码<br>
fprintf(stderr, "time out/n");<br>
break;<br>
default:<br>
fprintf(stderr, "[%d] ignores/n", signo);<br>
}<br>
}<br>
void sig_handler2(int signo)<br>
{<br>
switch(signo){<br>
case SIGALRM:<br>
fprintf(stderr, "time out/n");<br>
break;<br>
default:<br>
fprintf(stderr, "[%d] ignores/n", signo);<br>
}<br>
}<br>
void<br>
pr_mask(const char *str)<br>
{<br>
sigset_t sigset;<br>
int errno_save;<br>
errno_save = errno; /* we can be called by signal handlers */<br>
if (sigprocmask(0, NULL, &sigset) < 0){<br>
fprintf(stderr, "sigprocmask error");<br>
exit(1);<br>
}<br>
printf("%s", str);<br>
if (sigismember(&sigset, SIGINT)) printf("SIGINT ");<br>
if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");<br>
if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");<br>
if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");<br>
/* remaining signals can go here */<br>
printf("/n");<br>
errno = errno_save;<br></span>
</pre>
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值