信号机制

什么是信号?

信号是UNIX/Linux系统中进程间通信的一种机制,用于通知进程发生了某个异步事件。信号是软件中断,可以中断进程的正常执行流程。

常见信号

信号名称
信号编号
默认动作
描述

SIGHUP

1

终止

终端挂起

SIGINT

2

终止

键盘中断(Ctrl+C)

SIGQUIT

3

终止+core

键盘退出(Ctrl+\)

SIGILL

4

终止+core

非法指令

SIGABRT

6

终止+core

调用abort()

SIGFPE

8

终止+core

浮点异常

SIGKILL

9

终止

强制终止(不可捕获)

SIGSEGV

11

终止+core

段错误

SIGPIPE

13

终止

管道破裂

SIGALRM

14

终止

定时器到期

SIGTERM

15

终止

终止信号(可捕获)

SIGCHLD

17

忽略

子进程状态改变

SIGCONT

18

继续

继续执行

SIGSTOP

19

停止

暂停执行(不可捕获)

SIGTSTP

20

停止

键盘停止(Ctrl+Z)

信号处理

进程可以采取三种方式处理信号:

  1. 默认处理:执行信号的默认动作

  2. 忽略信号:大多数信号可以被忽略(除了SIGKILL和SIGSTOP)

  3. 捕获信号:定义信号处理函数来响应信号

信号相关命令

# 发送信号
$ kill -SIGTERM <pid>        # 发送SIGTERM信号
$ kill -9 <pid>              # 发送SIGKILL信号
$ kill -HUP <pid>            # 发送SIGHUP信号

# 查看信号
$ kill -l                    # 列出所有信号
$ trap -l                    # 列出所有信号名称

# 捕获信号(在shell脚本中)
$ trap "echo 'Received SIGINT'" SIGINT
$ trap "cleanup" EXIT        # 在脚本退出时执行cleanup函数

# 忽略信号
$ trap "" SIGINT             # 忽略SIGINT信号
$ trap - SIGINT              # 恢复默认处理

信号示例

#!/bin/bash

# 捕获SIGINT信号
trap 'echo "脚本被中断!"; exit 1' SIGINT

echo "脚本开始运行..."
echo "按Ctrl+C来中断脚本"

count=0
while [ $count -lt 10 ]; do
    echo "计数: $count"
    sleep 1
    count=$((count + 1))
done

echo "脚本正常完成"

信号的应用场景

  1. 进程控制:启动、停止、暂停进程

  2. 进程通信:通知进程某些事件

  3. 错误处理:处理异常情况

  4. 资源管理:清理资源,优雅退出

注意事项

  • SIGKILLSIGSTOP不能被捕获或忽略

  • 信号处理函数应该尽量简单

  • 在信号处理函数中避免调用不安全函数

  • 信号可能会在任意时间点到达

参考资料

最后更新于