🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 简介 信号是 Linux 进程间通信的最古老的方式。信号是软件中断,它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式 。信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断,转而处理某一个突发事件。 **信号的特点** * 简单 * 不能携带大量信息 * 满足某个特设条件才发送 信号可以直接进行用户空间进程和内核空间进程的交互,内核进程可以利用它来通知用户空间进程发生了哪些系统事件。 一个完整的信号周期包括三个部分:信号的产生,信号在进程中的注册,信号在进程中的注销,执行信号处理函数 ![](https://img.kancloud.cn/e4/0d/e40d246b4bd96d7d78750213c24db28d_641x232.png) 注意:这里信号的产生,注册,注销时信号的内部机制,而不是信号的函数实现 **信号编号:** Unix早期版本就提供了信号机制,但不可靠,信号可能丢失。Berkeley 和 AT&T都对信号模型做了更改,增加了可靠信号机制。但彼此不兼容。POSIX.1对可靠信号例程进行了标准化。 Linux 可使用命令:kill -l("l" 为字母),查看相应的信号 ~~~ [root@master ~]# kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX ~~~ 不存在编号为0的信号。其中1-31号信号称之为常规信号(也叫普通信号或标准信号),34-64称之为实时信号,驱动编程与硬件相关。名字上区别不大。而前32个名字各不相同 Linux常规信号一览表 | **编号** | **信号** | **对应事件** | **默认动作** | | --- | --- | --- | --- | | 1 | SIGHUP | 用户退出shell时,由该shell启动的所有进程将收到这个信号 | 终止进程 | | 2 | **SIGINT** | 当用户按下了****组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号 | 终止进程 | | 3 | **SIGQUIT** | 用户按下****组合键时产生该信号,用户终端向正在运行中的由该终端启动的程序发出些信号 | 终止进程 | | 4 | SIGILL | CPU检测到某进程执行了非法指令 | 终止进程并产生core文件 | | 5 | SIGTRAP | 该信号由断点指令或其他 trap指令产生 | 终止进程并产生core文件 | | 6 | SIGABRT | 调用abort函数时产生该信号 | 终止进程并产生core文件 | | 7 | SIGBUS | 非法访问内存地址,包括内存对齐出错 | 终止进程并产生core文件 | | 8 | SIGFPE | 在发生致命的运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为0等所有的算法错误 | 终止进程并产生core文件 | | 9 | SIGKILL | 无条件终止进程。本信号不能被忽略,处理和阻塞 | 终止进程,可以杀死任何进程 | | 10 | SIGUSE1 | 用户定义的信号。即程序员可以在程序中定义并使用该信号 | 终止进程 | | 11 | **SIGSEGV** | 指示进程进行了无效内存访问(段错误) | 终止进程并产生core文件 | | 12 | SIGUSR2 | 另外一个用户自定义信号,程序员可以在程序中定义并使用该信号 | 终止进程 | | 13 | **SIGPIPE** | Broken pipe向一个没有读端的管道写数据 | 终止进程 | | 14 | SIGALRM | 定时器超时,超时的时间 由系统调用alarm设置 | 终止进程 | | 15 | SIGTERM | 程序结束信号,与SIGKILL不同的是,该信号可以被阻塞和终止。通常用来要示程序正常退出。执行shell命令Kill时,缺省产生这个信号 | 终止进程 | | 16 | SIGSTKFLT | Linux早期版本出现的信号,现仍保留向后兼容 | 终止进程 | | 17 | **SIGCHLD** | 子进程结束时,父进程会收到这个信号 | 忽略这个信号 | | 18 | SIGCONT | 如果进程已停止,则使其继续运行 | 继续/忽略 | | 19 | SIGSTOP | 停止进程的执行。信号不能被忽略,处理和阻塞 | 为终止进程 | | 20 | SIGTSTP | 停止终端交互进程的运行。按下组合键时发出这个信号 | 暂停进程 | | 21 | SIGTTIN | 后台进程读终端控制台 | 暂停进程 | | 22 | SIGTTOU | 该信号类似于SIGTTIN,在后台进程要向终端输出数据时发生 | 暂停进程 | | 23 | SIGURG | 套接字上有紧急数据时,向当前正在运行的进程发出些信号,报告有紧急数据到达。如网络带外数据到达 | 忽略该信号 | | 24 | SIGXCPU | 进程执行时间超过了分配给该进程的CPU时间 ,系统产生该信号并发送给该进程 | 终止进程 | | 25 | SIGXFSZ | 超过文件的最大长度设置 | 终止进程 | | 26 | SIGVTALRM | 虚拟时钟超时时产生该信号。类似于SIGALRM,但是该信号只计算该进程占用CPU的使用时间 | 终止进程 | | 27 | SGIPROF | 类似于SIGVTALRM,它不公包括该进程占用CPU时间还包括执行系统调用时间 | 终止进程 | | 28 | SIGWINCH | 窗口变化大小时发出 | 忽略该信号 | | 29 | SIGIO | 此信号向进程指示发出了一个异步IO事件 | 忽略该信号 | | 30 | SIGPWR | 关机 | 终止进程 | | 31 | SIGSYS | 无效的系统调用 | 终止进程并产生core文件 | | 34~64 | SIGRTMIN ~ SIGRTMAX | LINUX的实时信号,它们没有固定的含义(可以由用户自定义) | 终止进程 | # 信号四要素 每个信号必备4要素,分别是: 1)编号 2)名称 3)事件 4)默认处理动作 可通过**man 7 signal**查看帮助文档获取 ![](https://img.kancloud.cn/d9/72/d9722b830687ed4562f0267ff81b6446_767x511.png) 在标准信号中,有一些信号是有三个“Value”,第一个值通常对alpha和sparc架构有效,中间值针对x86、arm和其他架构,最后一个应用于mips架构。一个‘-’表示在对应架构上尚未定义该信号。 不同的操作系统定义了不同的系统信号。因此有些信号出现在Unix系统内,也出现在Linux中,而有的信号出现在FreeBSD或Mac OS中却没有出现在Linux下。这里我们只研究Linux系统中的信号。 Action为默认动作: * Term:终止进程 * Ign: 忽略信号 (默认即时对该种信号忽略操作) * Core:终止进程,生成Core文件。(查验死亡原因,用于gdb调试) * Stop:停止(暂停)进程 * Cont:继续运行进程 注意通过man 7 signal命令查看帮助文档,其中可看到 : The signals**SIGKILL**and**SIGSTOP**cannot be caught, blocked, or ignored. 这里特别强调了**9) SIGKILL****和19) SIGSTOP信号,不允许忽略和捕捉,只能执行默认动作。甚至不能将其设置为阻塞。** 另外需清楚,只有每个信号所对应的事件发生了,该信号才会被递送(但不一定递达),不应乱发信号!! # 信号的状态 **1) 产生** a) 当用户按某些终端键时,将产生信号。 终端上按“Ctrl+c”组合键通常产生中断信号 SIGINT 终端上按“Ctrl+\\”键通常产生中断信号 SIGQUIT 终端上按“Ctrl+z”键通常产生中断信号 SIGSTOP 等。 b) 硬件异常将产生信号。 除数为 0,无效的内存访问等。这些情况通常由硬件检测到,并通知内核,然后内核产生适当的信号发送给相应的进程。 c) 软件异常将产生信号。 当检测到某种软件条件已发生(如:定时器alarm),并将其通知有关进程时,产生信号。 d) 调用系统函数(如:kill、raise、abort)将发送信号。 注意:接收信号进程和发送信号进程的所有者必须相同,或发送信号进程的所有者必须是超级用户。 e) 运行 kill /killall命令将发送信号。 此程序实际上是使用 kill 函数来发送信号。也常用此命令终止一个失控的后台进程。 **2) 未决状态:没有被处理** **3) 递达状态:信号被处理了** # 阻塞信号集和未决信号集 信号的实现手段导致信号有很强的延时性,但对于用户来说,时间非常短,不易察觉。 Linux内核的进程控制块PCB是一个结构体,task\_struct, 除了包含进程id,状态,工作目录,用户id,组id,文件描述符表,还包含了信号相关的信息,主要指**阻塞信号集和未决信号集**。 **6.1 阻塞信号集(信号屏蔽字)** 将某些信号加入集合,对他们设置屏蔽,当屏蔽x信号后,再收到该信号,该信号的处理将推后(处理发生在解除屏蔽后)。 **6.2 未决信号集** 信号产生,未决信号集中描述该信号的位立刻翻转为1,表示信号处于未决状态。当信号被处理对应位翻转回为0。这一时刻往往非常短暂。 信号产生后由于某些原因(主要是阻塞)不能抵达。这类信号的集合称之为未决信号集。在屏蔽解除前,信号一直处于未决状态。 在PCB中有两个非常重要的信号集。一个称之为“阻塞信号集”,另一个称之为“未决信号集”。 这两个信号集都是内核使用**位图机制**来实现的。但操作系统不允许我们直接对其进行位操作。而需自定义另外一个集合,借助信号集操作函数来对PCB中的这两个信号集进行修改。 ![](https://img.kancloud.cn/8e/e9/8ee9ccdac78a97308accf61a0738dcf9_799x481.png)