1.用户输入命令,在shell下启动一个进程。 2.按下ctrl+c,这是键盘输入产生一个硬件中断,被os获取,解释成信号,发送给前台进程 3.前台进程收到信号,进而引起进程退出。 ps:信号是进程之间事件异步通知的一种方式,属于软中断
使用命令 kill -l 可以查看信号
捕捉一下2号信号使ctrl+c失效,但是可以使用其他信号中断(ctrl+\)
#include<signal.h> #include<stdio.h> void hehe(int sig){ printf("signal=%d\n",sig); } int main() { signal(2,hehe); while(1); return 0; }ps:我们在C/C++当中除零,内存越界等异常,在系统层面上,是被当成信号处理的
信号处理函数是一个独立的执行流,和原来的用户代码之间没有相互调用的关系 信号处理函数执行过程中,原有的执行流就在等待
有时候信号不会立刻被处理,而是等到何时的时机在进行处理
实际执行信号的处理动作称为信号递达(Delivery);信号从产生到递达之间的状态,称为信号未决(Pending);进程可以选择阻塞 (Block )某个信号;被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作;注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作;一个函数如果在多个执行流中被调用,就可能出现问题‘
一个函数如果可重入,就意味着在多个执行流中调用是没问题的。
一个函数如果不可重入,在多个执行流中调用就是有问题的。
如果一个函数使用了全局变量/静态变量,不可重入
如果一个函数调用了不可重入函数,也是不可重入的,
如下创建20次子进程应该结束20次子进程打印20次child exit,可实际没有退出完,出现了僵尸进程,是因为在同时收到多个信号,只执行了一次。
#include<signal.h> #include<stdio.h> #include<sys/wait.h> #include<unistd.h> #include<stdlib.h> void hehe(int sig) { printf("child exit\n"); wait(NULL); } int main() { //signal(SIGCHLD, SIG_IGN); signal(17,hehe); int i = 0; for(;i<20; ++i){ pid_t ret = fork(); if(ret == 0){ printf("hehehepid %d\n",getpid()); exit(0); } } while(1) { sleep(1); } return 0; }//signal(SIGCHLD, SIG_IGN); 捕获信号之后