<signal.h> 是 C 标准库中的一个头文件,用于处理程序中的信号。信号是一种异步通知机制,通常用于在程序中发生特定事件时进行中断、暂停或其他处理。通过 <signal.h>,程序可以设置对不同信号的处理方式,如忽略信号、捕获信号并处理,或执行默认的操作。


📖 目录

  1. <signal.h> 简介
  2. 常见信号处理函数
  3. 常见信号类型
  4. 信号处理机制
  5. 示例代码
  6. 参考资料

1️⃣ <signal.h> 简介

  • 作用<signal.h> 提供了信号处理的功能,允许程序捕获并响应操作系统发送的信号。信号通常用于通知程序一些事件发生,例如用户中断、非法操作、定时器到期等。
  • 常见应用:中断处理、程序终止、错误处理、定时任务。

2️⃣ 常见信号处理函数

<signal.h> 定义了几种常用的信号处理函数,主要是用来设置信号的处理方式。

📌 signal

signal 函数用于定义信号的处理方式。

原型:

void (*signal(int signum, void (*handler)(int)))(int);

  • 参数
    • signum:信号编号。
    • handler:信号处理函数的指针,指定如何处理信号。可以是:
      • 一个函数的指针,该函数会在信号发生时执行。
      • SIG_IGN,表示忽略该信号。
      • SIG_DFL,表示执行信号的默认处理方式(例如,程序终止)。
  • 返回值:返回前一个信号处理器的地址,如果发生错误返回 SIG_ERR

📌 raise

raise 函数用于向程序自身发送信号。

原型:

int raise(int signum);

  • 参数signum:要发送的信号的编号。
  • 返回值:如果信号成功发送,返回 0;如果发送失败,返回 非零值

📌 abort

abort 函数用于强制程序中止,通常用于错误处理。

原型:

void abort(void);

  • 返回值:该函数不会返回,程序会立即终止。

3️⃣ 常见信号类型

C 标准库中的信号类型通常与操作系统事件相关,常见的信号包括:

信号名称描述
SIGINT用户中断信号(通常由 Ctrl+C 触发)。
SIGTERM程序终止信号,通常用于请求程序正常退出。
SIGSEGV段错误(访问非法内存区域时触发)。
SIGFPE算术错误信号(如除以零或溢出)。
SIGILL非法指令信号,通常表示程序执行了不合法的机器指令。
SIGABRT调用 abort 函数时触发的信号,程序异常终止。
SIGBUS总线错误信号(如访问未对齐的内存)。
SIGKILL强制终止信号,不能被捕获、阻塞或忽略,通常用于系统级别的强制终止。
SIGSTOP暂停信号,程序可以被暂停,但不能被捕获、忽略或处理。
SIGCONT恢复信号,用于恢复被暂停的进程。

4️⃣ 信号处理机制

信号处理机制包括以下几个关键点:

📌 信号的发送与接收

信号是由操作系统发送的,当程序发生特定的事件时,操作系统会生成一个信号并发送给程序。程序可以通过信号处理函数捕获这些信号并采取相应的行动。

📌 信号的处理方式

信号可以通过以下方式进行处理:

  1. 忽略信号:通过 SIG_IGN 忽略信号。
  2. 执行默认处理:通过 SIG_DFL 执行信号的默认处理行为(如程序终止)。
  3. 自定义处理函数:使用 signal 函数指定自定义的信号处理函数。

📌 信号的阻塞与解除阻塞

信号可以在程序的某些部分被阻塞,防止在临界区域内信号的处理。可以使用 sigprocmask 等函数来设置信号的阻塞状态。


5️⃣ 示例代码

📌 示例:捕获 SIGINT 信号

该示例演示了如何使用 signal 函数捕获 SIGINT 信号并进行处理。

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

void signal_handler(int signum) {
    printf("Received signal %d, terminating gracefully...\n", signum);
    exit(0);
}

int main() {
    // 捕获 SIGINT 信号(Ctrl+C)
    signal(SIGINT, signal_handler);

    printf("Program is running. Press Ctrl+C to terminate.\n");
    
    while (1) {
        // 程序持续运行,等待信号
    }

    return 0;
}

输出

Program is running. Press Ctrl+C to terminate.
Received signal 2, terminating gracefully...

解释

  1. 使用 signal(SIGINT, signal_handler) 捕获 SIGINT 信号(通常是按 Ctrl+C 产生的信号)。
  2. 当用户按下 Ctrl+C 时,程序会调用 signal_handler 函数并优雅地终止。

📌 示例:使用 raise 发送信号

该示例展示了如何使用 raise 函数向程序自身发送信号。

#include <stdio.h>
#include <signal.h>

void signal_handler(int signum) {
    printf("Received signal %d\n", signum);
}

int main() {
    // 捕获 SIGUSR1 信号
    signal(SIGUSR1, signal_handler);

    // 发送 SIGUSR1 信号
    raise(SIGUSR1);

    return 0;
}

输出

Received signal 10

解释

  1. 使用 signal(SIGUSR1, signal_handler) 捕获 SIGUSR1 信号。
  2. 通过 raise(SIGUSR1) 向程序发送 SIGUSR1 信号,触发 signal_handler 函数。

6️⃣ 参考资料

📖 C 标准库官方文档 – signal.h
📖 GNU C Library – signal.h
📖 ISO C 标准(PDF)


📌 总结

<signal.h> 提供了信号处理的机制,允许程序捕获、发送信号以及自定义信号的处理方式。信号是程序中用于处理异步事件的一种重要工具,如程序中断、错误处理、定时任务等。通过设置信号处理函数,程序可以根据不同的信号采取适当的行动,如错误恢复、资源清理等。