c语言中的信号处理:学习<signal.h>

发布于:2024-12-22 ⋅ 阅读:(15) ⋅ 点赞:(0)

<signal.h> 是 C 标准库的重要头文件,用于处理信号的发送与捕获,支持异步事件通知机制。以下是它的完整解读,包括信号的基础概念、常用宏与函数解析:


信号基础

信号是操作系统提供的一种进程间通信方式,用于通知进程发生了特定的事件。信号可以由操作系统、硬件或进程本身触发。

  • 信号处理机制
    • 默认动作:每种信号都有默认处理动作(如终止进程、忽略信号等)。
    • 捕获处理:通过用户自定义的信号处理函数捕获信号。
    • 忽略信号:使用 SIG_IGN 忽略信号。
    • 不可捕获/忽略信号:如 SIGKILLSIGSTOP

示例程序

#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...

关键数据类型

  1. sig_atomic_t

    • 类型:整数类型(int)。
    • 用途:信号处理函数中用作全局变量,保证对该变量的操作是原子的。
    • 示例:
      volatile sig_atomic_t flag = 0;
      
  2. 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 挂起进程直到信号到来。

注意事项

  1. 线程安全性

    • 信号处理程序中应避免使用不可重入的函数(如 printf)。
    • 推荐使用 sig_atomic_t 类型的变量。
  2. 信号屏蔽

    • 使用 sigprocmask 可以防止特定信号在关键代码段被处理。
  3. 高级处理

    • 建议使用 sigaction 替代 signal,它支持更精细的控制。