|
结构sigaction定义如下:
|
sa_handler字段包含一个信号捕捉函数的地址
sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加进进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。
sa_flag是一个选项,主要理解两个
|
最后一个参数是一个替代的信号处理程序,当设置SA_SIGINFO时才会用他,具体有些烦,暂时用不到,不看了。
下面的代码是用sigaction实现signal函数:
#
include
"apue.h"
Sigfunc *
signal
(
int
signo,
Sigfunc *
func)
{
struct
sigaction
act;
//新的信号关联信息
struct
sigaction
oact;
//老的信号关联信息
act.
sa_handler =
func;
//新的信号处理函数
sigemptyset
(
&
act.
sa_mask)
;
//初始化屏蔽字
act.
sa_flags =
0;
//初始化flags
if
(
signo =
=
SIGALRM)
{//不会重启动
#
ifdef
SA_INTERRUPT
act.
sa_flags |
=
SA_INERRUPT;
#
endif
}
else
{ //重启动
#
ifdef
SA_RESTART
act.
sa_flags |
=
SA_RESTART;
#
endif
}
if
(
sigaction
(
signo,
&
act,
&
oact)
<
0)//新老交换
return
(
SIG_ERR
)
;
return
(
oact.
sa_handler)
;
}
于signal 函数和 sigaction 函数的区别
注意 :
<1> sigaction
*一般用法:
19
20 phan.sa_handler = &sig_handler;
21 sigemptyset(&phan.sa_mask);
23 phan.sa_flags = 0; 或 //phan.sa_flags = SA_RESTART; 其效果和signal 一样
24 sigaction(SIGALRM, &phan, NULL);
*注意
一般不是重启动的函数,除非把sa_flag=SA_RESTART.
也就是说当信号到来,中断其阻塞的I/O操作,或其他阻塞的操作时,
他们会自动启动这些操作,而不会中断这些操作.而这些I/O操作会保持原来的阻塞状态就好好象根本没有信号到来一样.
<2>signal
函数是重启动的,
当使用该函数安装信号处理函数时,其阻塞的操作将会被中断
实际使用例子:
/*
* test for alarm
*/
#include "apue.h"
void sig_handler(int signo);
void sig_handler2(int signo);
void pr_mask(const char *str);
int
main(void)
{
int i;
struct sigaction phan;
char str[100] = {'/0'};
//phan.sa_handler = &sig_handler2;
phan.sa_handler = &sig_handler;
sigemptyset(&phan.sa_mask);
//phan.sa_flags = SA_RESTART; //如果使用这一行,将会阻塞在read函数
phan.sa_flags = 0;
sigaction(SIGALRM, &phan, NULL);
//signal(SIGALRM, sig_handler2);
for(i=0;;i++){
alarm(3);
fprintf(stderr, "do something/n");
read(STDIN_FILENO, str, sizeof(str));
fprintf(stderr, "[%d] done/n", i);
//alarm(0);
//pause();
}
return(0);
}
void sig_handler(int signo)
{
struct sigaction phan;
switch(signo){
case SIGALRM:
//如果下面的函数将会阻塞在read函数.因为它会让阻塞的操作自动重启动
//signal(SIGALRM, sig_handler);
phan.sa_handler = &sig_handler;
sigemptyset(&phan.sa_mask);
phan.sa_flags = 0;
sigaction(SIGALRM, &phan, NULL);
pr_mask("sig_handler : "); //打印出信号掩码
fprintf(stderr, "time out/n");
break;
default:
fprintf(stderr, "[%d] ignores/n", signo);
}
}
void sig_handler2(int signo)
{
switch(signo){
case SIGALRM:
fprintf(stderr, "time out/n");
break;
default:
fprintf(stderr, "[%d] ignores/n", signo);
}
}
void
pr_mask(const char *str)
{
sigset_t sigset;
int errno_save;
errno_save = errno; /* we can be called by signal handlers */
if (sigprocmask(0, NULL, &sigset) < 0){
fprintf(stderr, "sigprocmask error");
exit(1);
}
printf("%s", str);
if (sigismember(&sigset, SIGINT)) printf("SIGINT ");
if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");
if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
/* remaining signals can go here */
printf("/n");
errno = errno_save;