sigaction 函数
sigaction 函数的功能与 signal 类似,用于检查或修改与指定信号相关联的处理动作,一般在应用中使用 sigaction 函数。
- /* sigaction函数 */
- /*
- * 函数功能: 检查或修改与指定信号相关联的处理动作;此函数取代之前的signal函数;
- * 返回值:若成功则返回0,若出错则返回-1;
- * 函数原型:
- */
- #include <signal.h>
- int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
- /*
- * 说明:
- * signo是要检查或修改其具体动作的信号编号;
- * 若act非空,则要修改其动作;
- * 若oact指针非空,则系统经由oact指针返回该信号上一个动作;
- *
- * struct sigaction 结构如下:
- */
- struct sigaction
- {
- void (* sa_handler)(int); /* addr of signal handler, or SIG_IGN, or SIG_DFL */
- sigset_t sa_mask; /* additional signals to block */
- int sa_flags; /* signal options */
- /* alternate handler */
- void (*sa_sigaction)(int, siginfo_t *, void *);
- };
- /*
- * 说明:
- * 当更改动作时,若sa_handler 字段包含一个信号捕捉函数的地址,则sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,
- * 这一信号集要加到进程的信号屏蔽字中。仅当从信号捕获函数返回时再将进程的信号屏蔽字复位为原先值;
- * 其中sa_flags标志如下:
- * (1)SA_INTERRUPT 由此信号中断的系统调用不会自动重启;
- * (2)SA_NOCLDSTOP 若signo是SIGCHLD,当子进程停止时,不产生此信号,当子进程终止时,仍然产生此信号;若已设置此标志,则当停止的进程继续运行时,不发送SIGCHLD信号;
- * (3)SA_NOCLDWAIT 若signo是SIGCHLD,当子进程停止时,不创建僵死进程;若调用进程后面调用wait,则调用进程阻塞,直到其所有子进程都终止,此时返回-1,并将errno设置为ECHILD;
- * (4)SA_NOEFER 当捕捉到此信号时,在执行其信号捕捉函数时,系统不自动阻塞此信号;
- * (5)SA_NOSTACK 若用signaltstack(2)声明了一替换栈,则将此信号传递给替换栈上的进程;
- * (6)SA_RESETHAND 在此信号捕捉函数入口处,将此信号的处理方式复位为SIG_DEL,并清除SA_SIGINFO标志;
- * (7)SA_RESTART 由此信号中断的系统调用会自动重启动;
- * (8)SA_SIGINFO 此选项对信号处理程序提供附加信息:一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针;
- */
- void handler(int signo);
- void handler(int signo, siginfo_t *info, void *context);
- //siginfo 的结构如下:
- struct siginfo{
- int sig_signo; //信号编号
- int sig_errno; //如果不是0,就是errno.h中的errno值
- int sig_code; //附加信息(取决于信号)
- pid_t si_pid; //发送信号的进程ID
- uid_t sig_uid; //发送信号的进程实际用户ID
- void *si_addr; //产生错误的地址
- int si_status; //退出值或者信号值
- long si_band; //SIGPOLL的band号
- //可能还会有其他的值。
- }
下面可以 sigaction 函数实现 signal 函数的功能:
- #include "apue.h"
- Sigfunc *signal(int signo, Sigfunc *func)
- {
- struct sigaction act, oact;
- /* 设置信号处理函数 */
- act.sa_handler = func;
- /* 初始化信号集 */
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- if(signo == SIGALRM)
- {/* 若是SIGALRM信号,则系统不会自动重启 */
- #ifdef SA_INTERRUPT
- act.sa_flags |= SA_INTERRUPT;
- #endif
- }
- else
- {/* 其余信号设置为系统会自动重启 */
- #ifdef SA_RESTART
- act.sa_flags |= SA_RESTART;
- #endif
- }
- /* 调用 sigaction 函数 */
- if(sigaction(signo, &act, &oact) < 0)
- return(SIG_ERR);
- return(oact.sa_handler);
- }
测试程序:
- #include <sys/types.h>
- #include "apue.h"
- #include <signal.h>
- static Sigfunc *Msignal(int signo, Sigfunc *func);
- static void sig_func(int signo);
- int main(void)
- {
- if(Msignal(SIGALRM,sig_func) == SIG_ERR)
- err_sys("SIGALRM error");
- if(Msignal(SIGHUP,sig_func) == SIG_ERR)
- err_sys("SIGHUP error");
- printf("kill...\n");
- kill(getpid(),SIGHUP);
- printf("alarm...\n");
- alarm(5);
- pause();
- printf("exit.\n");
- exit(0);
- }
- static void sig_func(int signo)
- {
- if(SIGHUP == signo)
- printf("Recevied kill.\n");
- else if(SIGALRM == signo)
- printf("Recevied alarm.\n");
- else
- printf("Recevied others.\n");
- }
- static Sigfunc *Msignal(int signo, Sigfunc *func)
- {
- struct sigaction act, oact;
- /* 设置信号处理函数 */
- act.sa_handler = func;
- /* 初始化信号集 */
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- if(signo == SIGALRM)
- {/* 若是SIGALRM信号,则系统不会自动重启 */
- #ifdef SA_INTERRUPT
- act.sa_flags |= SA_INTERRUPT;
- #endif
- }
- else
- {/* 其余信号设置为系统会自动重启 */
- #ifdef SA_RESTART
- act.sa_flags |= SA_RESTART;
- #endif
- }
- /* 调用 sigaction 函数 */
- if(sigaction(signo, &act, &oact) < 0)
- return(SIG_ERR);
- return(oact.sa_handler);
- }
输出结果:
- kill...
- Recevied kill.
- alarm...
- Recevied alarm.
- exit.