现在的位置: 首页 > 综合 > 正文

sigaction函数的详解

2013年10月07日 ⁄ 综合 ⁄ 共 3031字 ⁄ 字号 评论关闭
本文主要参考《unix环境高级编程》
 
sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)。
 

int
sigaction
(
int
signo,
const
struct
sigaction
*
restrict act,


              struct
sigaction
*
restrict oact)
;


结构sigaction定义如下:

struct
sigaction
{

  void
(
*
sa_handler)
(
int
)
;

  sigset_t sa_mask;

  int
sa_flag;

  void
(
*
sa_sigaction)
(
int
,
siginfo_t *
,
void
*
)
;

}
;


sa_handler字段包含一个信号捕捉函数的地址

sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加进进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。

sa_flag是一个选项,主要理解两个

SA_INTERRUPT 由此信号中断的系统调用不会自动重启
SA_RESTART 由此信号中断的系统调用会自动重启


SA_SIGINFO 提供附加信息,一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针

最后一个参数是一个替代的信号处理程序,当设置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;

抱歉!评论已关闭.