# 信号机制

![](https://drawings.jvns.ca/drawings/signals.jpeg)

## 什么是信号？

信号是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. **捕获信号**：定义信号处理函数来响应信号

## 信号相关命令

```bash
# 发送信号
$ 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              # 恢复默认处理
```

## 信号示例

```bash
#!/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. **资源管理**：清理资源，优雅退出

## 注意事项

* `SIGKILL`和`SIGSTOP`不能被捕获或忽略
* 信号处理函数应该尽量简单
* 在信号处理函数中避免调用不安全函数
* 信号可能会在任意时间点到达

## 参考资料

* [Linux信号手册](https://man7.org/linux/man-pages/man7/signal.7.html)
* [Julia's Drawings: Signals](https://drawings.jvns.ca/signals/)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook.cdxiaodong.life/linux-an-quan/overview/signals.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
