man 7 signal
(默认处理动作)
杀死父进程:
由父进程杀死3号子进程:
raise 函数,给本进程传递信号
abort 函数
setitimer 函数
(实现alarm)
(第一次5s发SIGALRM,之后每隔3s发一次。signal()函数用于捕捉信号)
实现alarm
信号集处理函数:
信号捕捉特性
- 进程正常运行时,默认PCB中有一个信号屏蔽字,假定为☆,它决定了进程自动屏蔽哪些信号。当注册了某个信号捕捉函数,捕捉到该信号以后,要调用该函数。而该函数有可能执行很长时间,在这期间所屏蔽的信号不由☆来指定。而是用sa_mask来指定。调用完信号处理函数,再恢复为☆。
- XXX信号捕捉函数执行期间,XXX信号自动被屏蔽。
- 阻塞的常规信号不支持排队,产生多次只记录一次。(后32个实时信号支持排队)
(在捕捉函数执行期间,屏蔽SIGINT [ctrl+c] 和 SIGQUIT [ctrl+])
利用SIGCHLD信号捕捉回收子进程:
如果在sigaction注册之前子进程都已结束,则catch不到SIGCHLD.可以先把SIGCHLD block掉,sigaction注册后恢复。
#include <stdio.h> #include <unistd.h> #include <sys/wait.h> #include <signal.h> void catch_sig(int num){ pid_t wpid; while((wpid=waitpid(-1,NULL,WNOHANG))>0){ printf("wait child %d ok ", wpid); } } int main() { int i=0; sigset_t myset,oldset; sigemptyset(&myset); sigaddset(&myset,SIGCHLD); sigprocmask(SIG_BLOCK,&myset,&oldset); pid_t pid; for(i=0;i<10;i++){ pid=fork(); if(pid==0){ break; } } if(i==10){ sleep(5); struct sigaction act; act.sa_flags=0; sigemptyset(&act.sa_mask); act.sa_handler=catch_sig; sigaction(SIGCHLD,&act,NULL); sigprocmask(SIG_SETMASK,&oldset,NULL); while(1){ sleep(1); } }else { printf("I am the %d child, pid=%d ", i, getpid()); //sleep(i); } return 0; }
利用信号实现父子进程相互报数:
#include <stdio.h> #include <unistd.h> #include <signal.h> int flag=0; int count; void cat_son(int num){
sleep(1); printf("%d ", count); count+=2; flag=1; } void cat_father(int num){
sleep(1); printf("%d ", count); count+=2; flag=1; } int main() { pid_t pid=fork(); if(pid==0){ count=1; pid_t ppid=getppid(); signal(SIGUSR1,cat_son); while(1){ if(flag==1){ kill(ppid,SIGUSR2); flag=0; } } }else{ sleep(1); count=2; signal(SIGUSR2,cat_father); kill(pid,SIGUSR1); while(1){ if(flag==1){ kill(pid,SIGUSR1); flag=0; } } } return 0; }
若catch中没有sleep,会卡死。子进程报完树后执行完kill(ppid,SIGUSR2),父进程开始报数,然后发送SIGUSR1给子进程,子进程报数,flag置为1,然后从kill(ppid,SIGUSR2)之后执行指令,flag=0,不会给父进程发送信号了。
另一种方法:
#include <stdio.h> #include <unistd.h> #include <signal.h> //int flag=0; int count; pid_t pid; void cat_son(int num){ //sleep(1); printf("%d ", count); count+=2; //flag=1; kill(getppid(),SIGUSR2); } void cat_father(int num){ //sleep(1); printf("%d ", count); count+=2; //flag=1; kill(pid,SIGUSR1); } int main() { pid=fork(); if(pid==0){ count=1; pid_t ppid=getppid(); signal(SIGUSR1,cat_son); while(1){ //if(flag==1){ // kill(ppid,SIGUSR2); // flag=0; //} } }else{ sleep(1); count=2; signal(SIGUSR2,cat_father); kill(pid,SIGUSR1); while(1){ //if(flag==1){ // kill(pid,SIGUSR1); //flag=0; //} } } return 0; }