信号屏蔽
信号忽略:系统仍然传递该信号,只是相应的进程不做任何处理
信号屏蔽:进程不捕获信号,信号处于未决状态,当不再屏蔽信号时可以捕获之前被屏蔽的信号。
信号集数据结构定义:
typedef __sigset_t sigset_t; #define _SIGSET_NWORDS (1024 / (8 * sizeof(unsigned long int))) typedef struct { //此结构体占据32 * 32 = 1024 bit 每bit对应一个信号 val[0]0-31位对应常用1-31信号 unsigned long int __val[_SIGSET_NWORDS]; }__sigset_t;
int sigprocmask (int __how, __const sigset_t *__restrict __set, sigset_t * __restrict __oset) :设置屏蔽信号集。成功0,否则-1.
第一个参数:更改该集的方式
- SIG_BLOCK : 将第2个参数描述的集合添加到当前进程屏蔽的信号集中
- SIG_UNBLOCK : 将第2个参数描述的集合从到当前进程屏蔽的信号集中删除。
- SIG_SETMASK : 无论之前屏蔽了哪些信号,设置当前屏蔽集为第2个参数描述的对象。
如果set是空指针,则how没有意义,不会更改屏蔽信号集,因此可以查询当前屏蔽的信号集合。
int sigpending (sigset_t * __set) :获取当前未决的信号。成功0,否则-1.
int sigemptyset (sigset_t * __set) : 清空信号集
int sigfillset (sigset_t * __set) :将set的所有位都置为1.
int sigaddset (sigset_t *__set, int __signo) : 添加信号到信号集set
int sigdelset (sigset_t * __set, int __signo) : 从set中删除信号
int sigismember (__const sigset_t *__set, int __signo) : 检测信号是否在信号集,是返回1,否则返回0
int sigisemptyset (__const sigset_t * __set) : 检测信号集是否为空信号集
int sigandset (sigset_t *__set, __const sigset_t *__left, __const sigset_t *__right) : 用逻辑与的方式将两个信号合并
int sigorset (sigset_t *__set, __const sigset_t *__left, __const sigset_t *__right) : 用逻辑或的方式将两个信号合并
当一个信号在处理的过程中,相同的信号会暂时屏蔽,防止信号处理嵌套。
等待信号
int pause (void) :等待除了当前屏蔽信号集合外的任意信号
int sigsuspend (__const sigset_t * __set) :将当前进程屏蔽的信号集替换为其参数所指定的信号集合,直到收到非指定集合中的信号才继续执行
注意 不能屏蔽SIGKILL和SIGSTOP
信号应用例子
功能是复制文件,父进程执行复制操作,如果收到SIGUSR1信号则打印当前复制进度;子进程每隔固定时间向父进程发送SIGUSR1信号,通过SIGALARM
#include<stdio.h> #include<fcntl.h> #include<unistd.h> #include<stdlib.h> #include<string.h> #include<signal.h> #include<stdlib.h> int count; //当前复制大小 int file_size; //文件大小 void sig_alarm(int arg); //处理alarm信号 void sig_usr(int sig); //处理普通信号SIGUSR1 int main(int argc, char *argv[]) { pid_t pid; int i; int fd_src, fd_des; char buf[128]; //复制操作临时空间 if(argc != 3) { printf("check the format:comm src_file des_file "); return -1; } if((fd_src = open(argv[1], O_RDONLY)) == -1) { perror("open file src"); exit(EXIT_FAILURE); } file_size = lseek(fd_src, 0, SEEK_END); //获取资源文件大小 lseek(fd_src, 0, SEEK_SET); //重新设置读写位置为文件头 if((fd_des = open(argv[2], O_RDWR|O_CREAT, 0644)) == -1) { perror("open fd_fdes"); exit(EXIT_FAILURE); } if((pid = fork()) == -1) { perror("fork"); exit(EXIT_FAILURE); } else if(pid > 0) { signal(SIGUSR1, sig_usr); //安装信号SIGUSR1 do { memset(buf, '