元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
进程管理
▶
进程调度
调度策略
完全公平调度器
实时调度机制
▶
进程通信
信号机制
共享内存
管道与命名管道
▶
进程状态
上下文切换
僵尸进程处理
进程生命周期
▶
内存管理
▶
虚拟内存
页表机制
地址空间布局
TLB管理
▶
物理内存
伙伴系统
slab分配器
内存碎片处理
▶
文件系统
▶
VFS抽象层
inode机制
文件描述符
挂载机制
▶
具体文件系统
Ext4日志机制
Btrfs特性
Proc文件系统
▶
设备驱动
▶
驱动模型
设备树解析
sysfs接口
热插拔处理
▶
网络栈
▶
协议栈架构
sk_buff结构
Netfilter框架
套接字实现
▶
内核同步机制
▶
锁机制
自旋锁实现
RCU机制
Mutex与信号量
▶
启动过程
▶
引导阶段
GRUB交互
内核解压缩
早期初始化
▶
系统调用
▶
调用机制
陷入门实现
vsyscall优化
安全审计
▶
虚拟化和容器支持
▶
容器技术
命名空间隔离
cgroups实现
OverlayFS原理
发布时间:
2025-03-23 10:34
↑
☰
# Linux信号机制详解 信号是Linux系统中进程间通信的一种重要机制,用于通知进程发生了异步事件。本文将详细介绍Linux的信号机制。 ## 基本概念 ### 信号的定义 1. 信号类型 - 标准信号: 1-31 - 实时信号: 32-64 - 每个信号都有特定含义 2. 常见信号 ```c #define SIGHUP 1 // 终端挂起 #define SIGINT 2 // 终端中断(Ctrl+C) #define SIGQUIT 3 // 终端退出(Ctrl+\) #define SIGILL 4 // 非法指令 #define SIGTRAP 5 // 跟踪陷阱 #define SIGABRT 6 // 异常终止 #define SIGBUS 7 // 总线错误 #define SIGFPE 8 // 浮点异常 #define SIGKILL 9 // 强制终止 #define SIGUSR1 10 // 用户自定义信号1 #define SIGSEGV 11 // 段错误 #define SIGUSR2 12 // 用户自定义信号2 #define SIGPIPE 13 // 管道破裂 #define SIGALRM 14 // 定时器到期 #define SIGTERM 15 // 终止 ``` ### 信号处理 1. 默认行为 - 终止进程 - 忽略信号 - 暂停进程 - 继续进程 2. 信号掩码 - 阻塞信号传递 - 临时保存信号 - 解除阻塞后处理 ## 实现机制 ### 信号数据结构 1. 进程信号描述 ```c struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); }; ``` 2. 信号集操作 ```c typedef struct { unsigned long sig[_NSIG_WORDS]; } sigset_t; ``` ### 信号处理流程 1. 信号注册 ```c int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); ``` 2. 信号发送 ```c int kill(pid_t pid, int sig); int raise(int sig); ``` 3. 信号递送 ```c // 内核处理流程 do_signal() { // 检查是否有待处理信号 if (has_pending_signals()) { // 获取最高优先级信号 sig = get_signal_to_deliver(); // 调用信号处理函数 handle_signal(sig); } } ``` ## 信号编程 ### 信号处理函数 1. 简单处理 ```c #include <signal.h> void signal_handler(int signo) { if (signo == SIGINT) { printf("Caught SIGINT\n"); exit(0); } } int main() { if (signal(SIGINT, signal_handler) == SIG_ERR) { perror("signal"); exit(1); } while(1) pause(); return 0; } ``` 2. 高级处理 ```c #include <signal.h> void sigaction_handler(int signo, siginfo_t *info, void *context) { printf("Signal %d received from PID %ld\n", signo, (long)info->si_pid); } int main() { struct sigaction act; act.sa_sigaction = sigaction_handler; act.sa_flags = SA_SIGINFO; sigemptyset(&act.sa_mask); if (sigaction(SIGUSR1, &act, NULL) == -1) { perror("sigaction"); exit(1); } while(1) pause(); return 0; } ``` ### 信号集操作 1. 信号集管理 ```c #include <signal.h> int main() { sigset_t set; // 初始化信号集 sigemptyset(&set); // 添加信号 sigaddset(&set, SIGINT); sigaddset(&set, SIGTERM); // 阻塞信号 sigprocmask(SIG_BLOCK, &set, NULL); // 执行关键代码 // ... // 解除阻塞 sigprocmask(SIG_UNBLOCK, &set, NULL); return 0; } ``` 2. 信号等待 ```c #include <signal.h> int main() { sigset_t set; int sig; sigemptyset(&set); sigaddset(&set, SIGUSR1); // 阻塞SIGUSR1 sigprocmask(SIG_BLOCK, &set, NULL); // 等待信号 sigwait(&set, &sig); printf("Received signal %d\n", sig); return 0; } ``` ## 最佳实践 1. 信号处理原则 - 保持处理函数简单 - 避免使用不可重入函数 - 正确处理errno - 考虑信号嵌套 2. 可靠性考虑 - 使用sigaction代替signal - 合理设置信号掩码 - 避免竞态条件 - 处理信号丢失情况 3. 调试技巧 - 使用strace跟踪信号 - 记录信号处理日志 - 设置信号处理超时 - 模拟各种信号场景 ## 调试与监控 ### 调试工具 1. strace ```bash # 跟踪进程信号 strace -e signal ./program ``` 2. gdb ```bash # 设置信号断点 (gdb) handle SIGUSR1 stop print ``` ### 性能监控 1. 信号统计 ```bash # 查看进程信号统计 cat /proc/[pid]/status | grep Sig ``` 2. 系统日志 ```bash # 查看信号相关日志 dmesg | grep -i signal ``` ## 总结 Linux的信号机制是一种简单而有效的进程间通信方式,它通过异步事件通知的方式实现进程控制和状态同步。理解信号机制的工作原理和正确使用方法对于开发可靠的Linux应用程序非常重要。在实际应用中,我们应该遵循最佳实践,合理处理各种信号场景,并通过适当的调试手段确保程序的正确性。