《unix环境高级编程》信号——sigaction 函数

来源:互联网 发布:人机界面数据记录 编辑:程序博客网 时间:2024/05/21 05:37

sigaction 函数

sigaction 函数的功能与 signal 类似,用于检查或修改与指定信号相关联的处理动作,一般在应用中使用 sigaction 函数。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* sigaction函数 */  
  2. /* 
  3.  * 函数功能: 检查或修改与指定信号相关联的处理动作;此函数取代之前的signal函数; 
  4.  * 返回值:若成功则返回0,若出错则返回-1; 
  5.  * 函数原型: 
  6.  */  
  7. #include <signal.h>  
  8. int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);  
  9. /* 
  10.  * 说明: 
  11.  * signo是要检查或修改其具体动作的信号编号; 
  12.  * 若act非空,则要修改其动作; 
  13.  * 若oact指针非空,则系统经由oact指针返回该信号上一个动作; 
  14.  * 
  15.  * struct sigaction 结构如下: 
  16.  */  
  17. struct sigaction  
  18. {  
  19.     void (* sa_handler)(int);   /* addr of signal handler, or SIG_IGN, or SIG_DFL */  
  20.     sigset_t sa_mask;           /* additional signals to block */  
  21.     int sa_flags;               /* signal options */  
  22.   
  23.     /* alternate handler */  
  24.     void (*sa_sigaction)(int, siginfo_t *, void *);  
  25. };  
  26. /* 
  27.  * 说明: 
  28.  * 当更改动作时,若sa_handler 字段包含一个信号捕捉函数的地址,则sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前, 
  29.  * 这一信号集要加到进程的信号屏蔽字中。仅当从信号捕获函数返回时再将进程的信号屏蔽字复位为原先值; 
  30.  * 其中sa_flags标志如下: 
  31.  * (1)SA_INTERRUPT    由此信号中断的系统调用不会自动重启; 
  32.  * (2)SA_NOCLDSTOP    若signo是SIGCHLD,当子进程停止时,不产生此信号,当子进程终止时,仍然产生此信号;若已设置此标志,则当停止的进程继续运行时,不发送SIGCHLD信号; 
  33.  * (3)SA_NOCLDWAIT    若signo是SIGCHLD,当子进程停止时,不创建僵死进程;若调用进程后面调用wait,则调用进程阻塞,直到其所有子进程都终止,此时返回-1,并将errno设置为ECHILD; 
  34.  * (4)SA_NOEFER       当捕捉到此信号时,在执行其信号捕捉函数时,系统不自动阻塞此信号; 
  35.  * (5)SA_NOSTACK      若用signaltstack(2)声明了一替换栈,则将此信号传递给替换栈上的进程; 
  36.  * (6)SA_RESETHAND    在此信号捕捉函数入口处,将此信号的处理方式复位为SIG_DEL,并清除SA_SIGINFO标志; 
  37.  * (7)SA_RESTART      由此信号中断的系统调用会自动重启动; 
  38.  * (8)SA_SIGINFO      此选项对信号处理程序提供附加信息:一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针; 
  39.  */  
sa_sigaction 字段是一个替代的信号处理程序,当在 sigaction 结构中使用了 SA_SIGINFO 标志时,使用该信号处理程序。通常,按下列方式调用信号处理程序:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. void handler(int signo);  
如果设置了 SA_SIGINFO 标志,那么按照下列方式调用信号处理程序:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. void handler(int signo, siginfo_t *info, void *context);  
  2. //siginfo 的结构如下:  
  3. struct siginfo{  
  4.     int sig_signo;  //信号编号  
  5.     int sig_errno; //如果不是0,就是errno.h中的errno值  
  6.     int sig_code; //附加信息(取决于信号)  
  7.     pid_t si_pid; //发送信号的进程ID  
  8.     uid_t sig_uid; //发送信号的进程实际用户ID  
  9.     void *si_addr; //产生错误的地址  
  10.     int si_status; //退出值或者信号值  
  11.     long si_band; //SIGPOLL的band号  
  12.     //可能还会有其他的值。  
  13. }  

下面可以 sigaction 函数实现 signal 函数的功能:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "apue.h"  
  2.   
  3. Sigfunc *signal(int signo, Sigfunc *func)  
  4. {  
  5.     struct sigaction act, oact;  
  6.   
  7.     /* 设置信号处理函数 */  
  8.     act.sa_handler = func;  
  9.     /* 初始化信号集 */  
  10.     sigemptyset(&act.sa_mask);  
  11.     act.sa_flags = 0;  
  12.     if(signo == SIGALRM)  
  13.     {/* 若是SIGALRM信号,则系统不会自动重启 */  
  14. #ifdef SA_INTERRUPT  
  15.         act.sa_flags |= SA_INTERRUPT;  
  16. #endif  
  17.     }  
  18.     else  
  19.     {/* 其余信号设置为系统会自动重启 */  
  20. #ifdef SA_RESTART  
  21.         act.sa_flags |= SA_RESTART;  
  22. #endif  
  23.     }  
  24.     /* 调用 sigaction 函数 */  
  25.     if(sigaction(signo, &act, &oact) < 0)  
  26.         return(SIG_ERR);  
  27.     return(oact.sa_handler);  
  28. }  

测试程序:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <sys/types.h>  
  2. #include "apue.h"  
  3. #include <signal.h>  
  4.   
  5. static Sigfunc *Msignal(int signo, Sigfunc *func);  
  6. static void sig_func(int signo);  
  7.   
  8. int main(void)  
  9. {  
  10.     if(Msignal(SIGALRM,sig_func) == SIG_ERR)  
  11.         err_sys("SIGALRM error");  
  12.     if(Msignal(SIGHUP,sig_func) == SIG_ERR)  
  13.         err_sys("SIGHUP error");  
  14.     printf("kill...\n");  
  15.     kill(getpid(),SIGHUP);  
  16.     printf("alarm...\n");  
  17.     alarm(5);  
  18.     pause();  
  19.     printf("exit.\n");  
  20.     exit(0);  
  21. }  
  22.   
  23. static void sig_func(int signo)  
  24. {  
  25.     if(SIGHUP == signo)  
  26.         printf("Recevied kill.\n");  
  27.     else if(SIGALRM == signo)  
  28.         printf("Recevied alarm.\n");  
  29.     else  
  30.         printf("Recevied others.\n");  
  31. }  
  32.   
  33. static Sigfunc *Msignal(int signo, Sigfunc *func)  
  34. {  
  35.     struct sigaction act, oact;  
  36.   
  37.     /* 设置信号处理函数 */  
  38.     act.sa_handler = func;  
  39.     /* 初始化信号集 */  
  40.     sigemptyset(&act.sa_mask);  
  41.     act.sa_flags = 0;  
  42.     if(signo == SIGALRM)  
  43.     {/* 若是SIGALRM信号,则系统不会自动重启 */  
  44. #ifdef SA_INTERRUPT  
  45.         act.sa_flags |= SA_INTERRUPT;  
  46. #endif  
  47.     }  
  48.     else  
  49.     {/* 其余信号设置为系统会自动重启 */  
  50. #ifdef SA_RESTART  
  51.         act.sa_flags |= SA_RESTART;  
  52. #endif  
  53.     }  
  54.     /* 调用 sigaction 函数 */  
  55.     if(sigaction(signo, &act, &oact) < 0)  
  56.         return(SIG_ERR);  
  57.     return(oact.sa_handler);  
  58. }  

输出结果:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. kill...  
  2. Recevied kill.  
  3. alarm...  
  4. Recevied alarm.  
  5. exit.  
0 0
原创粉丝点击