C 标准库 - <signal.h> 学习笔记

介绍

<signal.h> 是 C 标准库中的头文件,主要提供了信号相关的函数和宏定义。在 Linux 和 Unix 系统中,信号(Signal)是一种软件中断机制,用于通知进程发生了某个事件,比如键盘输入、定时器到期、硬件错误等。

常用函数

signal

cCopy Code
void (*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 Code
int 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 Code
int 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 Code
int 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 函数来安全地终止进程。