三十、Linux 进程与信号——信号的概念及 signal 函数

30.1 信号的基本概念

  • 信号(signal)机制是Linux 系统中最为古老的进程之间的通信机制,解决进程在正常运行过程中被中断的问题,导致进程的处理流程会发生变化
  • 信号是软件中断
  • 信号是异步事件
    •   不可预见
    • 信号有自己的名称和编号
    • 信号和异常处理机制
  • 信号发生的来源
    • 硬件来源:如按下键盘或其他硬件故障,信号是由驱动程序产生
    • 软件来源:最常用发送信号的系统函数是 kill(),raise(),alarm() 和 setitimer() 等函数,软件来源还包括一些非法运算等操作,软件设置条件(如:gdb调试),信号是由内核产生。

  查看系统当中的信号:kill -l

  

  • [1 ~ 31] 信号称为非实时信号
    • 发送的信号可能丢失,不支持信号排队
  • [32 ~ 64] 信号称为实时信号
    • 发送的多个实时信号都会被接受,支持信号排队
  • 信号无优先  信号定义的地方:/usr/include/bits/signum.h 和 signum-generic.h

30.2 信号的处理和变革

30.2.1 信号的处理

  • 忽略信号
    • SIGKILL 和 SIGSTOP 永远不能忽略
    • 忽略硬件异常
    • 进程启动时 SIGUSR1 和 SIGUSR2 两个信号被忽略
  • 执行默认操作
    • 每个信号有默认动作,大部分信号默认动作是终止进程
  • 捕获信号
    • 告诉内核出现信号时调用自己的处理函数
    • SIGKILL 和 SIGSTOP 不能被捕获

30.2.2 信号变革

  • 信号出现在早期的 UNIX 中
  • 早期信号模型是不可靠的
  • BSD 和 SYSTEM V 分别对早期信号进行扩展,但是相互不兼容
  • POSIX 统一了上述两种模型,提供了可靠信号模型  

30.3 signal 函数

1 #include <signal.h>
2 void (*signal(int signo, void (*func)(int )))(int );
  • 函数功能:向内核登记信号处理函数
  • 函数参数:
    • signo:要登记的信号值
    • func:
      • 信号处理函数指针
      • SIG_IGN:忽略信号
      • SIG_DFL:采用系统默认的方式处理信号,执行默认操作
  • 返回值:若成功,则返回先前的信号处理函数指针,出错,则返回 SIG_ERR 

  signal 函数原型如下:

  

  

 1 #include <signal.h>
 2 #include <stdlib.h>
 3 #include <stdio.h>
 4 #include <unistd.h>
 5 
 6 /** 定义信号处理函数
 7  *  signo   进程捕获到的信号
 8  */
 9 void sig_handler(int signo)
10 {
11     printf("%d, %d occured\n", getpid(), signo);
12 }
13 
14 int main(void)
15 {
16     /** 向内核登记信号处理函数以及信号值 */
17     if(signal(SIGTSTP, sig_handler) == SIG_ERR) {
18         perror("signal sigtstp error");
19     }
20 
21     if(signal(SIGINT, sig_handler) == SIG_ERR) {
22         perror("signal sigint error");
23     }
24 
25     if(signal(SIGUSR1, sig_handler) == SIG_ERR) {
26         perror("signal usr1 error");
27     }
28 
29     if(signal(SIGUSR2, sig_handler) == SIG_ERR) {
30         perror("signal usr2 error");
31     }
32 
33     if(signal(SIGKILL, SIG_IGN) == SIG_ERR) {
34         perror("signal sigtstp error");
35     }
36 
37     if(signal(SIGSTOP, SIG_IGN) == SIG_ERR) {
38         perror("signal sigint error");
39     }
40     int i = 0;
41     while(i < 30) {
42         printf("%d out %d\n", getpid(), i++);
43         sleep(50);
44     }
45 
46     return 0;
47 }

 

 

posted @ 2018-12-30 21:52  游戏进行中  阅读(466)  评论(0编辑  收藏  举报