C库 —— <signal.h>

引言

在C语言编程中,<signal.h> 库提供了一组用于处理信号的函数和宏。信号是由操作系统或程序本身生成的一种异步事件,用于通知程序某些事件的发生,例如非法操作、用户中断等。掌握 <signal.h> 库的功能对于编写健壮和响应迅速的C程序至关重要。本文将详细介绍 <signal.h> 库的各个方面,包括其函数、用法及在实际编程中的应用。

<signal.h> 库的基本功能

<signal.h> 库包含许多重要的函数和宏,这些函数和宏可以分为以下几类:

  1. 信号处理函数
  2. 信号宏
  3. 信号集操作函数

我们将逐一介绍这些函数和宏的详细内容及其使用方法。

1. 信号处理函数

信号处理函数用于捕获和处理各种信号。<signal.h> 库提供了以下常用的信号处理函数:

  • signal:设置信号处理程序
  • raise:向当前程序发送信号
signal 函数

signal 函数用于设置信号处理程序,其基本语法如下:

#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);

示例代码:

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

void handle_sigint(int sig) {
    printf("Caught signal %d\n", sig);
}

int main() {
    // 设置 SIGINT 信号的处理程序
    signal(SIGINT, handle_sigint);

    while (1) {
        printf("Running...\n");
        sleep(1);
    }

    return 0;
}

在上面的示例中,当用户按下 Ctrl+C 发送 SIGINT 信号时,程序将调用 handle_sigint 函数并打印消息。

raise 函数

raise 函数用于向当前程序发送信号,其基本语法如下:

#include <signal.h>
int raise(int sig);

示例代码:

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

void handle_signal(int sig) {
    printf("Signal %d received\n", sig);
}

int main() {
    // 设置 SIGUSR1 信号的处理程序
    signal(SIGUSR1, handle_signal);

    printf("Sending SIGUSR1 to the current program\n");
    raise(SIGUSR1);

    return 0;
}

在上面的示例中,程序向自身发送 SIGUSR1 信号,触发 handle_signal 函数并打印消息。

2. 信号宏

<signal.h> 库定义了许多常用的信号宏,用于表示不同类型的信号。以下是一些常用的信号宏及其描述:

信号宏描述
SIGABRT程序异常终止信号
SIGFPE浮点异常信号
SIGILL非法指令信号
SIGINT中断信号(通常由 Ctrl+C 产生)
SIGSEGV段错误信号
SIGTERM终止信号
SIGUSR1用户定义信号 1
SIGUSR2用户定义信号 2

示例代码:

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

void handle_sigterm(int sig) {
    printf("Received SIGTERM signal\n");
}

int main() {
    // 设置 SIGTERM 信号的处理程序
    signal(SIGTERM, handle_sigterm);

    while (1) {
        printf("Running...\n");
        sleep(1);
    }

    return 0;
}

在上面的示例中,当程序接收到 SIGTERM 信号时,将调用 handle_sigterm 函数并打印消息。

3. 信号集操作函数

<signal.h> 库还提供了一组用于操作信号集的函数,这些函数包括:

  • sigemptyset:初始化信号集为空
  • sigfillset:将所有信号添加到信号集中
  • sigaddset:将指定信号添加到信号集中
  • sigdelset:从信号集中删除指定信号
  • sigismember:检查指定信号是否在信号集中
  • sigprocmask:设置或检查当前的信号屏蔽
  • sigpending:获取未决信号集
  • sigsuspend:等待信号
sigemptysetsigfillset 函数

sigemptyset 函数用于初始化信号集为空,其基本语法如下:

#include <signal.h>
int sigemptyset(sigset_t *set);

sigfillset 函数用于将所有信号添加到信号集中,其基本语法如下:

#include <signal.h>
int sigfillset(sigset_t *set);

示例代码:

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

int main() {
    sigset_t set;

    // 初始化信号集为空
    sigemptyset(&set);

    // 将所有信号添加到信号集中
    sigfillset(&set);

    return 0;
}
sigaddsetsigdelset 函数

sigaddset 函数用于将指定信号添加到信号集中,其基本语法如下:

#include <signal.h>
int sigaddset(sigset_t *set, int signum);

sigdelset 函数用于从信号集中删除指定信号,其基本语法如下:

#include <signal.h>
int sigdelset(sigset_t *set, int signum);

示例代码:

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

int main() {
    sigset_t set;

    // 初始化信号集为空
    sigemptyset(&set);

    // 将 SIGINT 信号添加到信号集中
    sigaddset(&set, SIGINT);

    // 从信号集中删除 SIGINT 信号
    sigdelset(&set, SIGINT);

    return 0;
}
sigismember 函数

sigismember 函数用于检查指定信号是否在信号集中,其基本语法如下:

#include <signal.h>
int sigismember(const sigset_t *set, int signum);

示例代码:

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

int main() {
    sigset_t set;

    // 初始化信号集为空
    sigemptyset(&set);

    // 将 SIGINT 信号添加到信号集中
    sigaddset(&set, SIGINT);

    // 检查 SIGINT 是否在信号集中
    if (sigismember(&set, SIGINT)) {
        printf("SIGINT is in the set\n");
    } else {
        printf("SIGINT is not in the set\n");
    }

    return 0;
}
sigprocmask 函数

sigprocmask 函数用于设置或检查当前的信号屏蔽,其基本语法如下:

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

示例代码:

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

int main() {
    sigset_t set, oldset;

    // 初始化信号集为空
    sigemptyset(&set);

    // 将 SIGINT 信号添加到信号集中
    sigaddset(&set, SIGINT);

    // 屏蔽 SIGINT 信号
    sigprocmask(SIG_BLOCK, &set, &oldset);

    // 检查 SIGINT 是否被屏蔽
    if (sigismember(&oldset, SIGINT)) {
        printf("SIGINT was blocked\n");
    } else {
        printf("SIGINT was not blocked\n");
    }

    return 0;
}
sigpending 函数

sigpending 函数用于获取未决信号集,其基本语法如下:

#include <signal.h>
int sigpending(sigset_t *set);

示例代码:

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

void handle_signal(int sig) {
    printf("Signal %d received\n", sig);
}

int main() {
    sigset_t set, pending;

    // 初始化信号集为空
    sigemptyset(&set);

    // 将 SIGUSR1 信号添加到信号集中
    sigaddset(&set, SIGUSR1);

    // 屏蔽 SIGUSR1 信号
    sigprocmask(SIG_BLOCK, &set, NULL);

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

    // 获取未决信号集
    sigpending(&pending);

    // 检查 SIGUSR1 是否在未决信号集中
    if (sigismember(&pending, SIGUSR1)) {
        printf("SIGUSR1 is pending\n");
    } else {
        printf("SIGUSR1 is not pending\n");
    }

    // 恢复信号屏蔽状态
    sigprocmask(SIG_UNBLOCK, &set, NULL);

    return 0;
}
sigsuspend 函数

sigsuspend 函数用于等待信号,其基本语法如下:

#include <signal.h>
int sigsuspend(const sigset_t *mask);

示例代码:

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

void handle_signal(int sig) {
    printf("Signal %d received\n", sig);
}

int main() {
    sigset_t set;

    // 设置 SIGUSR1 信号的处理程序
    signal(SIGUSR1, handle_signal);

    // 初始化信号集为空
    sigemptyset(&set);

    // 将 SIGUSR1 信号添加到信号集中
    sigaddset(&set, SIGUSR1);

    // 屏蔽 SIGUSR1 信号
    sigprocmask(SIG_BLOCK, &set, NULL);

    printf("Waiting for SIGUSR1 signal...\n");

    // 等待信号
    sigsuspend(&set);

    return 0;
}

在上面的示例中,程序等待接收 SIGUSR1 信号,当信号到达时,程序将调用 handle_signal 函数并打印消息。

图表描述

为了更清晰地展示 <signal.h> 库的功能和用法,我们可以使用图表进行描述。以下是一些常见用法的图表:

  1. 常用信号宏及其描述
信号宏描述
SIGABRT程序异常终止信号
SIGFPE浮点异常信号
SIGILL非法指令信号
SIGINT中断信号(通常由 Ctrl+C 产生)
SIGSEGV段错误信号
SIGTERM终止信号
SIGUSR1用户定义信号 1
SIGUSR2用户定义信号 2
  1. 信号集操作函数
函数描述
sigemptyset初始化信号集为空
sigfillset将所有信号添加到信号集中
sigaddset将指定信号添加到信号集中
sigdelset从信号集中删除指定信号
sigismember检查指定信号是否在信号集中
sigprocmask设置或检查当前的信号屏蔽
sigpending获取未决信号集
sigsuspend等待信号
实际应用示例
示例一:捕获和处理 SIGINT 信号

以下代码示例展示了如何捕获和处理 SIGINT 信号(通常由 Ctrl+C 产生):

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

void handle_sigint(int sig) {
    printf("Caught signal %d\n", sig);
}

int main() {
    // 设置 SIGINT 信号的处理程序
    signal(SIGINT, handle_sigint);

    while (1) {
        printf("Running...\n");
        sleep(1);
    }

    return 0;
}

在上面的示例中,当用户按下 Ctrl+C 发送 SIGINT 信号时,程序将调用 handle_sigint 函数并打印消息。

示例二:发送和接收用户定义信号

以下代码示例展示了如何发送和接收用户定义的 SIGUSR1 信号:

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

void handle_signal(int sig) {
    printf("Signal %d received\n", sig);
}

int main() {
    // 设置 SIGUSR1 信号的处理程序
    signal(SIGUSR1, handle_signal);

    printf("Sending SIGUSR1 to the current program\n");
    raise(SIGUSR1);

    return 0;
}

在上面的示例中,程序向自身发送 SIGUSR1 信号,触发 handle_signal 函数并打印消息。

示例三:使用信号集操作函数

以下代码示例展示了如何使用信号集操作函数来屏蔽和恢复信号:

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

void handle_signal(int sig) {
    printf("Signal %d received\n", sig);
}

int main() {
    sigset_t set, oldset;

    // 设置 SIGUSR1 信号的处理程序
    signal(SIGUSR1, handle_signal);

    // 初始化信号集为空
    sigemptyset(&set);

    // 将 SIGUSR1 信号添加到信号集中
    sigaddset(&set, SIGUSR1);

    // 屏蔽 SIGUSR1 信号
    sigprocmask(SIG_BLOCK, &set, &oldset);

    printf("SIGUSR1 is blocked\n");

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

    // 检查 SIGUSR1 是否在未决信号集中
    sigpending(&set);
    if (sigismember(&set, SIGUSR1)) {
        printf("SIGUSR1 is pending\n");
    }

    // 恢复信号屏蔽状态
    sigprocmask(SIG_SETMASK, &oldset, NULL);

    printf("SIGUSR1 is unblocked\n");

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

    return 0;
}

在上面的示例中,程序首先屏蔽 SIGUSR1 信号并发送信号,然后检查信号是否在未决信号集中。最后,程序恢复信号屏蔽状态并再次发送信号。

结论

<signal.h> 库是C标准库中用于处理信号的重要工具。通过使用这些信号处理函数、信号宏和信号集操作函数,程序员可以编写出能够响应异步事件的健壮程序。本文详细介绍了 <signal.h> 库的各个函数和宏,并提供了实际应用示例和图表描述,帮助读者深入理解和掌握这些功能。希望本文对读者在C语言编程中的信号处理有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新华

感谢打赏,我会继续努力原创。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值