Linux信号:sigaction函数sa_flags各标志影响的实例讲解

#include
int sigaction(int sigon,const struct sigaction &restrict act,

            struct sigaction &restrict oact);
            成功返回0,出错返回-1
此函数使用下列结构:
struct sigaction{
 void    ( *sa_handler)(int); //信号处理函数地址 sigset_t sa_mask;       //一个调用信号捕捉函数之前要加到进程信号屏蔽字中的信号集
 int    sa_flags;       //信号处理选项
 
 void   (*sa_sigaction)(int,siginfo_t *,void *); 
}

对于sigaction 函数本身我们不做多介绍。我们重点是在 sa_flags 的不同值的情况下,sigaction函数的处理方式


SA_INTERRUPT:由此信号中断的系统调用不会自动重启动(针对sigaction的XSI默认处理方式不会自动重启) 

SA_RESTART:  由此信号中断的系统调用会自动重启。
   
   我们看下面这段程序:
 4 void sig_int(int signo){
  5         printf("\nint sig_int\n");
  6 }
  7 
  8 int main(void){
  9         struct sigaction new_action;
 10         new_action.sa_handler=sig_int;
 11         if(sigemptyset(&new_action.sa_mask)==-1){
 12                 printf("set new action mask error\n");
 13                 exit(1);
 14         }
 15         new_action.sa_flags=0;
 16 
 17         if(sigaction(SIGINT,&new_action,NULL)==-1){
 18                 printf("set SIGINT process error\n");
 19                 exit(1);
 20         }
 21         char c;
 22         read(0,&c,1);
 23         printf("read :%c\n",c);
 24         exit(0);
 25 }

第十五行中我们没有使用任何标志。设置捕捉 SIGINT 信号,然后读标准输入

输出如下:
   feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
 ^C
 int sig_int
 read :?
从输出我们看到 的确是一样的。

现在 我们将 第十五行改为  new_action.sa_flags=SA_RESTART; 再看看输出情况
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
get signal:Child exited
child done
get signal:Child exited
parent done

正如 我们预测的。父进程先收到一次子进程暂停是而产生的SIGCHLD,然后当子进程结束时,父进程又接收到一次。
注意这段程序是有问题的,它存在一个竞争条件。如果fork是实现是父进程先执行而系统非常繁忙,可能父进程睡眠一秒后子进程还未运行。那么SIGCONT信号将
丢失,然后当子进程停止时,父进程收到信号中断睡眠(第二次的睡眠)然后结束进程。那么 子进程在结束前一直就是出于停止状态。我们也不会看到子进程打印的"child done"。
,如果你的系统是父进程先运行,你可以去掉父进程中的 sleep(1)实验一下。输出中是不会出现子进程打印的"child done")

现在我们修改下 第十七行 中的标志选项  new_action.sa_flags=SA_NOCLDSTOP;
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out &
[2] 4369
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out &
[2] 4410
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
father done
运行时,会发现只阻塞了两秒左右。

现在我们将 第九行改为:   action.sa_flags= SA_NOCLDWAIT;
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out &
[2] 5010

feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out &
[2] 5041
feng@ubuntu:~/learn_linux_c_second/chapter_10$ 
get signal:Interrupt
^C
[2]-  Segmentation fault      (core dumped) ./a.out

我们看到的确发生了段错误

SA_ONSTACK:

  若用sigaltstatck声明了一替换栈,则将此信号递送给替换栈上的进程。对于这个选项,我还没有接触,这里就不做介绍了


http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=28852942&id=3754478

你可能感兴趣的:(Linux,System,Program)