0. Linux提供了那些信号?
信号编号32之前的信号,称之为unix经典信号。
信号编号32之后的信号,称之为实时信号,驱动编程常用
1. 信号产生种类
1.1 特殊终端按键
1. Ctrl+C SIGINT 2. 3. Crtl+Z SIGTSTP 4. 5. Ctrl+\ SIGQUIT
1. 2硬件异常
1)除0操作
2)访问非法内存
1. 3 Kill函数或者kill指令
1. #include <sys/types.h> 2. 3. #include <signal.h> 4. 5. int kill(pid_t pid, int sig);
pid参数说明:
pid参数 |
说明 |
pid > 0 |
Sig发送给ID为pid的进程 |
Pid = 0 |
Sig信号发送给与调用kill的那个进程同组的所有进程 |
Pid = -1 |
sig信号将送往所有调用进程有权给其发送信号的进程,除了进程1(init)。 |
Pid < -1 |
sig发送给组ID为|-pid|的进程,并且发送进程具有向其发送信号的权限 |
sig参数为kill –l看到的前32个信号 |
1.4 某种软件条件已经发生
比喻定用alarm时器定时1s,当1s时间到达之后,会向系统发送SIGALARM信号,并终止当前进程
1. #include <stdio.h> 2. #include <unistd.h> 3. 4. 5. int main(void) 6. { 7. int counter; 8. alarm(1); 9. /* 10. 11. sleep(1)与alarm(1)的区别 12. sleep(1)就是睡在这里,下面的代码不去执行 13. alarm(1)只是定时1s,下面的代码还是会继续执行 14. */ 15. 16. for(counter=0; 1; counter++) 17. printf("counter = %d.\n", counter); 18. 19. return 0; 20. }
这段代码的作用就是测试当前机器1s可以执行多少次。
2. 进程处理信号行为
manpage里信号有3种处理方式
1.默认处理动作(man 7 signal可以看到)
1. Term Default action is to terminate the process. 2. 3. Ign Default action is to ignore the signal. 4. 5. Core Default action is to terminate the process and dump core (see core(5)). 6. 7. Stop Default action is to stop the process. 8. 9. Cont Default action is to continue the process if it is currently stopped.
2.忽略
3.捕捉(用户自定义信号处理函数,类似于中断服务程序)
3. 信号集处理函数
实际执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending)。进程可以选择阻塞(Block)某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。
下图给出信号从产生到抵达的执行过程
1、阻塞信号集是用户可以设置的,未决信号集是用户不能设置的;
2、系统规定有2个信号不能被阻塞,SIGKILL和SIGSTOP
3、内核向进程发送一个信号,到信号的执行过程分为以下步骤
(1)首先未决信号集对应的信号位会置1,
(2)去判断阻塞信号集对应的信号位是否为1,若为1则阻塞,若为0则信号递达,并执行handle
(3)当执行完之后,未决信号集对应的信号位被翻转成0
4、未决和阻塞标志都可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可表示每个信号的“有效”或“无效”状态。阻塞信号集中“有效”和“无效”分别表示该信号是否被阻塞;未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。
5、阻塞信号集也叫当前进程的信号屏蔽字(Signal mask),这里的屏蔽应该理解为阻塞而不是忽略。
4. C标准库提供的信号处理函数
signal函数和system函数
1. typedef void (*sighandler_t)(int) 2. 3. sighandler_t signal(int signum, sighandler_t handler)
程序:
1. #include <stdio.h> 2. #include <signal.h> 3. #include <unistd.h> 4. 5. 6. void do_sig(int n) 7. { 8. printf("hello.\n"); 9. } 10. 11. int main(void) 12. { 13. signal(SIGINT,do_sig); 14. 15. while(1){ 16. printf("*******************\n"); 17. sleep(1); 18. } 19. 20. return 0; 21. }
执行结果如下:
按下Ctrl+C 发送SIGINT信号,执行do_sig函数,打印hello