非异步信号安全函数
这个程序演示了如何使用sigaction
来捕获和处理信号(特别是SIGINT,即Ctrl+C)。以下是关键点和潜在问题的分析:
程序功能
- 信号捕获:注册自定义处理函数
handler
来捕获信号2(SIGINT,通常由Ctrl+C触发)。 - 循环输出:主函数无限循环每秒打印进程PID,捕获信号后继续运行,而非终止。
代码解析
-
信号处理设置:
struct sigaction act; act.sa_handler = handler; // 设置信号处理函数 sigaction(2, &act, &olact); // 注册SIGINT的处理方式
使用
sigaction
替换默认信号处理,旧的处理方式保存在olact
中。 -
处理函数:
void handler(int signum) {cout << "I catch a signal:" << signum << endl; }
当SIGINT触发时,输出信号编号。
潜在问题
-
非异步信号安全函数:
cout
在信号处理函数中使用可能不安全。信号处理应仅使用异步信号安全函数(如write
),避免竞争条件。
-
未初始化sigaction结构体:
act.sa_mask
和act.sa_flags
未显式设置。正确做法是清空sa_mask
并设置sa_flags
:sigemptyset(&act.sa_mask); act.sa_flags = 0; // 或 SA_RESTART 以自动重启被中断的系统调用
-
程序终止:
- 捕获SIGINT后,Ctrl+C无法终止程序。需通过其他信号(如
kill -9 PID
)终止。
- 捕获SIGINT后,Ctrl+C无法终止程序。需通过其他信号(如
改进建议
- 使用安全函数:
void handler(int signum) {const char* msg = "I catch a signal:2\n";write(STDOUT_FILENO, msg, strlen(msg)); }
- 正确初始化sigaction:
struct sigaction act = {}; act.sa_handler = handler; sigemptyset(&act.sa_mask); act.sa_flags = 0;
运行示例
- 编译并运行程序后,按下Ctrl+C会触发
handler
,输出信号信息。 - 程序继续运行,需用kill命令终止。
该程序展示了信号处理的基本用法,但需注意安全性和结构体初始化以确保稳定。