C 标准库 - <signal.h> 学习笔记
介绍
<signal.h> 是 C 标准库中的头文件,主要提供了信号相关的函数和宏定义。在 Linux 和 Unix 系统中,信号(Signal)是一种软件中断机制,用于通知进程发生了某个事件,比如键盘输入、定时器到期、硬件错误等。
常用函数
signal
cCopy Codevoid (*signal(int sig, void (*func)(int)))(int);
signal
函数用于设置某个信号的处理函数,即当进程收到指定信号时会调用该函数进行处理。常用的信号处理函数有 SIG_IGN
(忽略信号)和 SIG_DFL
(使用默认行为),也可以自定义信号处理函数。
例如,下面的代码演示了如何将 SIGINT
信号的处理函数设置为 signal_handler
:
cCopy Code#include <stdio.h>
#include <signal.h>
void signal_handler(int sig) {
printf("Received signal: %d\n", sig);
}
int main() {
// 设置 SIGINT 信号处理函数为 signal_handler
signal(SIGINT, signal_handler);
// 死循环等待信号
while (1) {}
return 0;
}
raise
cCopy Codeint raise(int sig);
raise
函数用于向当前进程发送指定信号。通常情况下,我们可以在程序中使用 raise(SIGTERM)
命令来安全地终止进程。
例如,下面的代码演示了如何在程序中向自身发送 SIGINT
信号:
cCopy Code#include <stdio.h>
#include <signal.h>
void signal_handler(int sig) {
printf("Received signal: %d\n", sig);
}
int main() {
signal(SIGINT, signal_handler);
// 发送 SIGINT 信号
raise(SIGINT);
return 0;
}
sigaction
cCopy Codeint sigaction(int sig, const struct sigaction *restrict act, struct sigaction *restrict oldact);
sigaction
函数用于修改指定信号的处理方式。和 signal
不同的是,sigaction
函数支持更加精细的信号处理方式,可以指定是否阻塞其他信号、是否恢复信号处理函数、是否使用 SA_RESTART 标志等。
例如,下面的代码演示了如何使用 sigaction
函数捕获 SIGINT
信号:
cCopy Code#include <stdio.h>
#include <signal.h>
void signal_handler(int sig) {
printf("Received signal: %d\n", sig);
}
int main() {
struct sigaction sa;
sa.sa_handler = signal_handler; // 设置信号处理函数
sa.sa_flags = SA_RESTART; // 使用 SA_RESTART 标志
// 注册信号处理函数
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
// 死循环等待信号
while (1) {}
return 0;
}
sigprocmask
cCopy Codeint sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oldset);
sigprocmask
函数用于修改当前进程的信号掩码。信号掩码是一个位图,每个位表示一个信号是否被屏蔽(阻塞)。当某个信号被屏蔽时,该信号会被暂时挂起,直到解除屏蔽。
例如,下面的代码演示了如何使用 sigprocmask
函数屏蔽 SIGINT
信号:
cCopy Code#include <stdio.h>
#include <signal.h>
void signal_handler(int sig) {
printf("Received signal: %d\n", sig);
}
int main() {
// 屏蔽 SIGINT 信号
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
perror("sigprocmask");
return 1;
}
// 设置 SIGINT 信号处理函数
signal(SIGINT, signal_handler);
// 死循环等待信号
while (1) {}
return 0;
}
实例
下面是一个简单的实例,演示了如何在程序中使用信号处理函数来处理 SIGTERM
信号,安全地终止进程:
cCopy Code#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
void signal_handler(int sig) {
printf("Received signal: %d\n", sig);
exit(0);
}
int main() {
// 设置 SIGTERM 信号处理函数
signal(SIGTERM, signal_handler);
// 死循环等待信号
while (1) {}
return 0;
}
在上面的代码中,我们首先使用 signal
函数设置 SIGTERM
信号的处理函数为 signal_handler
,然后进入死循环等待信号。当收到 SIGTERM
信号时,会调用 signal_handler
函数来安全地终止进程。