C标准库-signal.h

C 标准库 - <signal.h>
简介
<signal.h> 是 C 标准库中的一个头文件,用于处理信号。
signal.h 头文件定义了一个变量类型 sig_atomic_t、两个函数调用和一些宏来处理程序执行期间报告的不同信号。
信号是一种异步通知机制,允许进程在特定事件发生时执行预定义的处理函数。

下面是一个简单的示例程序,演示如何使用 signal 函数来捕捉 SIGINT 信号(通常由 Ctrl+C 产生)。

实例
#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 信号的处理程序设置为 handle_sigint 函数
    signal(SIGINT, handle_sigint);

    while (!stop) { // 检查是否应退出
        printf(“Running…\n”);
        sleep(1);
    }

    printf(“Exiting…\n”);

    return 0;
}

以上代码中,当程序运行时,如果用户按下 Ctrl+C,会捕捉到 SIGINT 信号并调用 handle_sigint 函数,打印出信号编号。
编译执行以上代码,输出结果如下:
Running…
Running…
Running…
^CCaught signal 2
Exiting…
代码解析:
volatile sig_atomic_t stop = 0;:定义一个全局变量 stop,用于指示程序是否应退出。使用 volatile 关键字确保编译器不会优化掉对该变量的访问,因为它可能在信号处理程序中被修改。sig_atomic_t 类型保证了对该变量的访问是原子的。在 handle_sigint 信号处理函数中,将 stop 设置为 1,指示程序应退出。在主循环中,检查 stop 变量的值,如果它被设置为 1,则跳出循环,结束程序。
库变量
下面是头文件 signal.h 中定义的变量类型:

序号变量 & 描述
1sig_atomic_t 这是 int 类型,在信号处理程序中作为变量使用。它是一个对象的整数类型,该对象可以作为一个原子实体访问,即使存在异步信号时,该对象可以作为一个原子实体访问。
2sigset_t 一种数据类型,用于表示信号集。

库宏
<在 C 标准库中,SIG_ 前缀的宏与 signal 函数一起使用,用于定义和处理信号的行为。下面是常见的 SIG_ 宏及其用途:

序号宏 & 描述
1 SIG_DFL表示信号的默认处理程序。使用此宏将信号恢复到其默认行为。
2 SIG_ERR表示信号处理函数设置出错的返回值。
3 SIG_IGN忽略信号。

信号类型:

常量描述SIGABRT由 abort 函数产生的信号,表示异常终止SIGALRM由 alarm 函数设定的定时器到期信号SIGBUS非法内存访问(例如,访问未对齐的内存地址)SIGCHLD子进程状态改变(退出或停止)SIGCONT继续执行被暂停的进程SIGFPE算术错误(例如,除零错误、浮点异常)SIGHUP挂起信号(通常用于检测终端断开)SIGILL非法指令SIGINT中断信号(通常由 Ctrl+C 产生)SIGKILL立即终止信号(不能被捕捉或忽略)SIGPIPE向无读进程的管道写数据SIGQUIT终端退出信号(通常由 Ctrl+\ 产生),生成核心转储SIGSEGV段错误(非法内存访问)SIGSTOP停止进程的执行(不能被捕捉或忽略)SIGTERM终止信号SIGTSTP暂停进程(通常由 Ctrl+Z 产生)SIGTTIN后台进程从终端读数据时产生的信号SIGTTOU后台进程向终端写数据时产生的信号SIGUSR1用户自定义信号 1SIGUSR2用户自定义信号 2SIGPOLLI/O 事件(取代 SIGIO)SIGPROF定时器到期信号(由 setitimer 设置的 profiling timer)SIGSYS非法系统调用SIGTRAP断点或陷阱指令SIGURG套接字紧急条件信号SIGVTALRM虚拟时钟定时器到期信号SIGXCPU超过 CPU 时间限制SIGXFSZ超过文件大小限制
库函数
下面是头文件 signal.h 中定义的函数:

函数
描述

void (*signal(int sig, void (*func)(int)))(int);
设置信号处理程序。

int raise(int sig);
向当前进程发送信号。

int kill(pid_t pid, int sig);
向指定进程发送信号。

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
检查或更改阻塞信号集。

int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact);
检查或更改信号处理程序。

int sigsuspend(const sigset_t *mask);
暂时替换当前信号屏蔽字并挂起进程直到捕捉到信号。

int sigpending(sigset_t *set);
检查未决信号集。

int sigemptyset(sigset_t *set);
初始化信号集为空集。

int sigfillset(sigset_t *set);
初始化信号集为全信号集。

int sigaddset(sigset_t *set, int signum);
向信号集中添加指定信号。

int sigdelset(sigset_t *set, int signum);
从信号集中删除指定信号。

int sigismember(const sigset_t *set, int signum);
检查指定信号是否在信号集中。

void abort(void);
产生 SIGABRT 信号,导致进程异常终止。

unsigned int alarm(unsigned int seconds);
在指定秒数后发送 SIGALRM 信号给调用进程。

int pause(void);
挂起进程直到捕捉到信号。

void psignal(int sig, const char *s);
打印信号描述信息。

char *strsignal(int sig);
返回信号描述字符串。

int sigwait(const sigset_t *set, int *sig);
阻塞等待信号并处理。