<signal.h>
是 C 标准库的重要头文件,用于处理信号的发送与捕获,支持异步事件通知机制。以下是它的完整解读,包括信号的基础概念、常用宏与函数解析:
信号基础
信号是操作系统提供的一种进程间通信方式,用于通知进程发生了特定的事件。信号可以由操作系统、硬件或进程本身触发。
- 信号处理机制
- 默认动作:每种信号都有默认处理动作(如终止进程、忽略信号等)。
- 捕获处理:通过用户自定义的信号处理函数捕获信号。
- 忽略信号:使用
SIG_IGN
忽略信号。 - 不可捕获/忽略信号:如
SIGKILL
和SIGSTOP
。
示例程序
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
// 全局变量,用于控制程序退出
volatile sig_atomic_t stop = 0;
// 信号处理函数
void handle_sigint(int sig) {
printf("Caught signal %d\n", sig);
stop = 1; // 设置退出标志
}
int main() {
// 设置 SIGINT 信号的处理程序
signal(SIGINT, handle_sigint);
while (!stop) { // 检查是否退出
printf("Running...\n");
sleep(1);
}
printf("Exiting...\n");
return 0;
}
程序说明:
- 使用
signal
函数捕获SIGINT
信号(Ctrl+C)。 - 定义
volatile sig_atomic_t stop
,确保信号处理的线程安全性。 handle_sigint
是信号处理函数,捕获到信号后修改stop
变量。- 主循环通过检查
stop
控制程序的退出。
运行结果:
Running...
Running...
Running...
^CCaught signal 2
Exiting...
关键数据类型
sig_atomic_t
- 类型:整数类型(
int
)。 - 用途:信号处理函数中用作全局变量,保证对该变量的操作是原子的。
- 示例:
volatile sig_atomic_t flag = 0;
- 类型:整数类型(
sigset_t
- 描述:用于表示信号集的类型。
- 常与以下函数配合使用:
sigemptyset
:初始化为空集。sigaddset
:向信号集中添加信号。sigdelset
:从信号集中删除信号。
重要宏
宏 | 描述 |
---|---|
SIG_DFL |
将信号处理恢复为默认动作。 |
SIG_IGN |
忽略信号。 |
SIG_ERR |
信号处理函数设置错误时的返回值。 |
常见信号类型
信号名称 | 描述 | 默认动作 |
---|---|---|
SIGABRT |
异常终止(由 abort 触发)。 |
终止进程,生成核心转储。 |
SIGINT |
中断信号(如按下 Ctrl+C)。 | 终止进程。 |
SIGKILL |
强制终止(不可捕获/忽略)。 | 终止进程。 |
SIGSEGV |
段错误(非法内存访问)。 | 终止进程,生成核心转储。 |
SIGTERM |
请求终止。 | 终止进程。 |
SIGSTOP |
停止进程(不可捕获/忽略)。 | 暂停进程。 |
SIGUSR1 |
用户自定义信号 1。 | 终止进程。 |
SIGUSR2 |
用户自定义信号 2。 | 终止进程。 |
常用函数
1. signal
定义:
void (*signal(int sig, void (*func)(int)))(int);
功能:设置信号的处理函数。
sig
:信号编号。func
:信号处理函数,可以是自定义函数或SIG_DFL
/SIG_IGN
。- 返回值:先前的信号处理函数指针。
2. raise
定义:
int raise(int sig);
功能:向当前进程发送指定信号。
3. kill
定义:
int kill(pid_t pid, int sig);
功能:向指定进程发送信号。
pid
:目标进程 ID。sig
:信号编号。
4. 信号集操作函数
函数 | 描述 |
---|---|
sigemptyset |
初始化为空信号集。 |
sigfillset |
初始化为全信号集。 |
sigaddset |
添加信号到信号集。 |
sigdelset |
从信号集中删除信号。 |
sigismember |
检查信号是否在信号集中。 |
5. 高级信号函数
函数 | 描述 |
---|---|
sigaction |
设置或获取信号处理动作,比 signal 更强大。 |
sigprocmask |
阻塞或解除阻塞信号。 |
sigpending |
获取未决信号集。 |
sigsuspend |
暂时替换信号屏蔽字,并挂起进程直到信号到来。 |
6. 定时器与挂起函数
函数 | 描述 |
---|---|
alarm |
在指定秒数后发送 SIGALRM 信号。 |
pause |
挂起进程直到信号到来。 |
注意事项
线程安全性:
- 信号处理程序中应避免使用不可重入的函数(如
printf
)。 - 推荐使用
sig_atomic_t
类型的变量。
- 信号处理程序中应避免使用不可重入的函数(如
信号屏蔽:
- 使用
sigprocmask
可以防止特定信号在关键代码段被处理。
- 使用
高级处理:
- 建议使用
sigaction
替代signal
,它支持更精细的控制。
- 建议使用