一、信号在内核
中的表示
执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending)。进程可以选择阻塞(Block)某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。信号在内核中的表示如下:
二、信号阻塞与未诀
三、信号集操作函数
(1)、信号集
函数声明:
#include <signal.h> int sigemptyset(sigset_t *set);//全部置0 int sigfillset(sigset_t *set);//全部置1 int sigaddset(sigset_t *set, int signum);//添加对应位 int sigdelset(sigset_t *set, int signum);//删除对应位 int sigismember(const sigset_t *set, int signum);//是否为1函数参数:信号集,信号代码
返回值:成功返回0,失败返回-1
(2)、读取或更改进程的信号屏蔽字
函数声明:
#include <signal.h> int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);函数参数: 改变方式,信号集,原来的信号集
返回值:成功返回0,失败返回-1并设置errno
如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。
如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。
示例:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <signal.h> #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ }while(0) void handle(int sig); void printsigset(sigset_t* set) { int i; for (i=1;i < 64; ++i) { if (sigismember(set,i)) putchar('1'); else putchar('0'); } printf("\n"); } int main(int argc,char* argv[]) { sigset_t pset; sigset_t bset; sigemptyset(&bset); sigaddset(&bset,SIGINT); if (signal(SIGINT,handle) == SIG_ERR) ERR_EXIT("signal error"); if (signal(SIGQUIT,handle) == SIG_ERR) ERR_EXIT("signal error"); sigprocmask(SIG_BLOCK,&bset,NULL); for(;;) { sigpending(&pset); printsigset(&pset); sleep(1); } return 0; } void handle(int sig) { printf("recv a sig=%d\n",sig); if (sig == SIGQUIT) { sigset_t uset; sigemptyset(&uset); sigaddset(&uset,SIGINT); sigprocmask(SIG_UNBLOCK,&uset,NULL); } }