1.功能sigaction
sigaction动与指定信号相关联的处理动作。其函数原型例如以下:
#inlcude <signal.h>
int sigaction(int signo,const struct sigaction * restrict act,struct sigaction * restrict act);
当中參数signo是要检測或改动其详细动作的信号编号。
若act指针非空,则要改动其动作。假设oact指针非空。则系统经由oact指针返回该信号的上一个动作。结构体sigaction的结构例如以下:
一旦对给定的信号设置了一个动作,那么在调用signation显式的改变它之前,该设置就一直有效。
act结构的sa_flags字段指定对信号进行处理的各个选项。下图具体列出了这些选项的意义。
sigaction结构的sa_sigaction字段是一个替代的信号处理程序。
当sa_flags设置了SA_SIGINFO标志时,使用该信号处理程序。
通常,信号处理函数的形式是这种:void handler(int signo)。
但假设设置了SA_SIGINFO标志,则信号处理函数的原型是这种:void handler(int signo,siginfo_t *info,void *context)。siginfo_t结构包括了信号产生原因的有关信息。
该结构的样式例如以下所看到的:
context參数是无类型指针。它可被强制类型转换为ucontext_t结构类型,该结构标识信号传递时的上下文信息。
2.函数sigsetjmp和siglongjmp
在信号处理程序中进行非局部转移时使用这两个函数。
#include <setjmp.h>
int sigsetjmp(sigjmp_buf env,int savemask);//若直接调用,返回0。若从siglongjmp调用返回,则返回非0。
void siglongjmp(sigjmp_buf env,int val);
在调用sigsetmask时。假设savemask值为1,则将进程当前的屏蔽字保存在env中。
调用siglongjmp时,假设带非0savemask的sigsetjmp调用已经将进程的屏蔽字保存在env中了。则siglongjmp从中恢复保存的信号屏蔽字。
例:
#include "apue.h" #include <setjmp.h> #include <time.h> static void sig_usr1(int); static void sig_alrm(int); static sigjmp_buf jmpbuf; static volatile sig_atomic_t canjump; 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) perror("sigprocmask error"); printf("mask: %s", str); if (sigismember(&sigset, SIGINT)) printf("SIGINT "); if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT "); if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 "); if (sigismember(&sigset, SIGUSR2)) printf("SIGUSR2 "); if (sigismember(&sigset, SIGALRM)) printf("SIGALRM "); /* remaining signals can go here */ printf(" "); errno = errno_save; } 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) { #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; #endif } else { act.sa_flags |= SA_RESTART; } if(sigaction(signo,&act,&oact) < 0) return (SIG_ERR); return (oact.sa_handler); } int main(void) { if(signal(SIGUSR1,sig_usr1) == SIG_ERR) err_sys("signal(SIGUSR1) error"); if(signal(SIGALRM,sig_alrm) == SIG_ERR) err_sys("signal(SIGALRM) error"); pr_mask("starting main:"); if(sigsetjmp(jmpbuf,1)) { pr_mask("ending main:"); exit(0); } canjump = 1; for(;;) pause(); } static void sig_usr1(int signo) { time_t starttime; if(canjump == 0) return; pr_mask("starting sig_usr1:"); alarm(3); starttime = time(NULL); for(;;) if(time(NULL) > starttime+5) break; pr_mask("finishing sig_usr1:"); canjump = 0; siglongjmp(jmpbuf,1); } static void sig_alrm(int signo) { pr_mask("in sig_alrm:"); }
3.函数sigsuspend
#include <signal.h>
int sigsuspend(const sigset_t * sigmask);
进程的信号屏蔽字设置由sigmask指定。
在捕捉到一个信号前,该进程被挂起。假设捕捉到一个信号,则sigsuspend返回,而且该进程的新高屏蔽字设置为曾经的值。
例:
#include "apue.h" static void sig_int(int); 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) perror("sigprocmask error"); printf("mask: %s", str); if (sigismember(&sigset, SIGINT)) printf("SIGINT "); if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT "); if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 "); if (sigismember(&sigset, SIGUSR2)) printf("SIGUSR2 "); if (sigismember(&sigset, SIGALRM)) printf("SIGALRM "); /* remaining signals can go here */ printf(" "); errno = errno_save; } 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) { #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; #endif } else { act.sa_flags |= SA_RESTART; } if(sigaction(signo,&act,&oact) < 0) return (SIG_ERR); return (oact.sa_handler); } int main(void) { sigset_t newmask,oldmask,waitmask; pr_mask("program start:"); if(signal(SIGINT,sig_int) == SIG_ERR) err_sys("signal(SIGINT) error"); sigemptyset(&waitmask); sigaddset(&waitmask,SIGUSR1); sigemptyset(&newmask); sigaddset(&newmask,SIGINT); if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0) err_sys("SIG_BLOCK error"); pr_mask("in critical region:"); if(sigsuspend(&waitmask) != -1) err_sys("suspend error"); pr_mask("after return from sigsuspend:"); if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0) err_sys("SIG_SETMASK error"); pr_mask("program end:"); } static void sig_int(int signo) { pr_mask("in sig_int:"); }
4.函数sigqueue
使用排队信号必须做一下几个操作:
(1)使用sigaction函数安装信号处理程序时指定SA_SIGINFO标志。
(2)在sigaction结构的sa_sigaction成员中提供信号处理程序。
(3)使用sigqueue函数发送信号。
#include <signal.h>
int sigqueue(pid_t pid,int signo,const union sigval value);
5.信号名和编号
能够通过psignal函数可移植地打印与信号编号相应的字符串。
#include <signal.h>
void psignal(int signal,const char * msg);//字符串msg输入到标准错误流
假设只需要字符信号的叙述性说明,可以用于strsignal功能。
#include <string.h>
char *strsignal(int signo);