Menu Close

进程间通信信号(Signals)详解

Linux 和 Unix 系统中,信号(Signal) 是一种进程间通信(IPC)机制,用于通知进程发生了某种事件。信号是一种异步的通知方式,操作系统或其他进程可以随时向目标进程发送信号,以让其执行特定的操作,如终止、暂停、继续运行等。


一) 什么是信号(Signals)?

  • 信号是进程间的异步通知机制,可以用于通知进程某个事件发生,如中断、终止、挂起等。
  • 进程可以接收、忽略、处理信号(但某些信号无法被捕获或忽略,如 SIGKILL)。
  • 信号是由 内核、用户、硬件 触发的。
  • 进程可以使用 kill 命令或 kill() 系统调用向其他进程发送信号。

二) 常见的 Linux 信号列表

信号编号 信号名称 默认动作 说明
1 SIGHUP 终止 终端关闭、会话结束时发送
2 SIGINT 终止 用户按 Ctrl+C 终止进程
3 SIGQUIT 终止 + Dump Ctrl+\ 退出进程,生成 core dump
9 SIGKILL 终止 强制终止进程,不可捕获/忽略
11 SIGSEGV 终止 + Dump 段错误(Segmentation Fault)
15 SIGTERM 终止 默认的进程终止信号,可被捕获和忽略
18 SIGCONT 继续 让一个停止的进程继续运行
19 SIGSTOP 停止 强制暂停进程,不可捕获/忽略
20 SIGTSTP 停止 Ctrl+Z 发送,让进程进入后台
  • SIGKILLSIGSTOP 无法被进程捕获或忽略,确保系统可以终止或挂起进程
  • SIGTERM最常用的终止进程信号,可由进程处理或忽略。

The number of possible signals is limited. The first 31 signals are standardized in LINUX; all have names starting with SIG. Some are from POSIX.


Notice SIGUSR1 and SIGUSR2. These are available for customized use.

在终端运行kill -l命令, 可查看Linux支持的信号列表:

Linux支持的信号signal列表
Linux支持的信号signal列表

其中,编号为1 ~ 31的信号为传统UNIX支持的信号,是不可靠信号(非实时的);编号为34 ~ 63的信号是后来扩充的,为可靠信号(实时信号)。
不可靠信号和可靠信号的区别在于前者不支持排队,可能会造成信号丢失,而后者不会。

不可靠信号和可靠信号的区别在于前者不支持排队,可能会造成信号丢失,而后者不会。

1 SIGHUP 挂起(在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联)
2 SIGINT 中断(程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出,用于通知前台进程组终止进程
3 SIGQUIT 退出(和SIGINT类似, 但由QUIT字符(通常是Ctrl-/)来控制. 进程在因收到SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号)
4 SIGILL 非法指令(执行了非法指令. 通常是因为可执行文件本身出现错误, 或者试图执行数据段. 堆栈溢出时也有可能产生这个信号)
5 SIGTRAP 断点或陷阱指令(由断点指令或其它trap指令产生. 由debugger使用)
6 SIGABRT abort发出的信号(调用abort函数生成的信号)
7 SIGBUS 非法内存访问(非法地址, 包括内存地址对齐(alignment)出错。比如访问一个四个字长的整数, 但其地址不是4的倍数。它与SIGSEGV的区别在于后者是由于对合法存储地址的非法访问触发的(如访问不属于自己存储空间或只读存储空间))
8 SIGFPE 浮点异常(在发生致命的算术运算错误时发出. 不仅包括浮点运算错误, 还包括溢出及除数为0等其它所有的算术的错误)
9 SIGKILL kill信号(用来立即结束程序的运行) 不能被忽略、处理和阻塞
10 SIGUSR1 用户信号1(留给用户使用)
11 SIGSEGV 无效内存访问(试图访问未分配给自己的内存, 或试图往没有写权限的内存地址写数据)
12 SIGUSR2 用户信号2(留给用户使用)
13 SIGPIPE 管道破损,没有读端的管道写数据(这个信号通常在进程间通信产生,比如采用FIFO(管道)通信的两个进程,读管道没打开或者意外终止还往管道写,写进程会收到SIGPIPE信号。此外用Socket通信的两个进程,写进程在写Socket的时候,读进程已经终止,也会产生这个信号)
14 SIGALRM alarm发出的信号(时钟定时信号, 计算的是实际的时间或时钟时间. alarm函数使用该信号)
15 SIGTERM 终止信号(程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和处理。通常用来要求程序自己正常退出,shell命令kill缺省产生这个信号)
16 SIGSTKFLT 栈溢出
17 SIGCHLD 子进程退出(子进程结束时, 父进程会收到这个信号) 默认忽略
18 SIGCONT 进程继续 不能被阻塞
19 SIGSTOP 进程停止(停止(stopped)进程的执行. 注意它和terminate以及interrupt的区别:该进程还未结束, 只是暂停执行) 不能被忽略、处理和阻塞
20 SIGTSTP 进程停止(停止进程的运行, 用户键入SUSP字符时(通常是Ctrl-Z)发出这个信号) 该信号可以被处理和忽略
21 SIGTTIN 进程停止,后台进程从终端读数据时
22 SIGTTOU 进程停止,后台进程想终端写数据时
23 SIGURG I/O有紧急数据到达当前进程 默认忽略
24 SIGXCPU 进程CPU时间片到期
25 SIGXFSZ 文件大小的超出上限
26 SIGVTALRM 虚拟时钟超时
27 SIGPROF profile时钟超时
28 SIGWINCH 窗口大小改变 默认忽略
29 SIGIO I/O相关
30 SIGPWR 关机 默认忽略
31 SIGSYS 系统调用异常
参考博文:


三) 发送信号

3.1) kill 命令

kill 用于向进程发送信号:

如果不指定信号,默认发送 SIGTERM

3.2)pkillkillall

pkill 通过进程发送信号:

killall 终止所有匹配名称的进程

3.3) kill() 系统调用

在 C 语言中,可以使用 kill() 发送信号:

3.4)raise() 向自己发送信号

3.5)sigqueue() 发送带数据的信号

四) 处理信号

进程可以使用 signal()sigaction() 处理信号。

4.1) signal() 处理信号

运行后,按 Ctrl+C 发送 SIGINT进程不会终止,而是打印 Received signal 2

4.2) sigaction() 处理信号

sigaction() 提供更强的信号控制功能:

sigaction() 可以替代 signal(),支持更高级的信号处理。

五)屏蔽信号

 sigprocmask() 屏蔽信号

可以使用 sigprocmask() 屏蔽信号,使进程暂时忽略某些信号:

SIG_BLOCK 屏蔽信号,SIG_UNBLOCK 解除屏蔽。

六) 挂起进程等待信号

6.1) pause() 等待信号

6.2) sigwait() 主动等待信号

7. 总结

  • 信号是进程间通信的重要方式,用于通知进程发生事件,如终止、暂停、继续等。
  • 进程可以使用 killraisesigqueue 发送信号。
  • 进程可以使用 signal()sigaction() 处理信号。
  • 可以使用 sigprocmask() 屏蔽信号,pause()sigwait() 挂起进程等待信号。

掌握信号机制对编写可靠的后台服务、守护进程、异常处理等至关重要!

除教程外,本网站大部分文章来自互联网,如果有内容冒犯到你,请联系我们删除!
Posted in 进程