嵌入式Linux系统编程 — 6.4 信号集

目录​​​​​​​

1 信号集概念

2 sigemptyset、sigfillset初始化信号集

3  sigaddset、sigdelset向信号集中添加/删除信号

4 sigismember函数测试信号是否在信号集中


1 信号集概念

在Linux系统中,信号集(signal set)用于表示一组信号的集合,信号集的使用主要涉及到信号的阻塞与未决状态的管理。很多系统调用都使用到了信号集这种数据类型来作为参数传递,譬如 sigaction()函数、 sigprocmask()函数、 sigpending()函数等。

信号集其实就是 sigset_t 类型数据结构:

# define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long int)))
typedef struct
{
    unsigned long int __val[_SIGSET_NWORDS];
} sigset_t;

宏定义 _SIGSET_NWORDS:

  • 这个宏定义计算了需要多少个unsigned long int来表示所有的信号。由于Linux系统支持的信号数量最多为1024(因系统而异),每个unsigned long int的大小是其位数除以8(即字节数),再乘以sizeof(unsigned long int)得到每个unsigned long int的位数。因此,(1024 / (8 * sizeof (unsigned long int)))计算了总共需要多少个unsigned long int来存储1024个信号的位图。

sigset_t 结构体:

  • sigset_t是一个结构体,它包含一个数组类型是unsigned long int__val的数组,长度由_SIGSET_NWORDS宏定义决定。

2 sigemptyset、sigfillset初始化信号集

sigemptyset()和 sigfillset()用于初始化信号集。 sigemptyset()初始化信号集,使其不包含任何信号;而sigfillset()函数初始化信号集,使其包含所有信号(包括所有实时信号),函数原型如下:

#include <signal.h>

int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
  • set: 指向需要进行初始化的信号集变量。
  • 返回值: 成功返回 0;失败将返回-1,并设置 errno。

这两个函数通常与 sigaction(), sigpending(), sigprocmask() 等函数一起使用,以控制进程对信号的响应和处理。例如,使用 sigfillset() 可以创建一个包含所有信号的信号集,然后通过 sigprocmask() 来阻塞或允许这些信号。

下面是一个简单的使用 sigemptyset()sigfillset() 的示例:

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

int main() 
{
    sigset_t set, oldset, emptyset;

    // 填充信号集
    if (sigfillset(&set) == -1) {
        perror("Error in sigfillset");
        return 1;
    }

    // 清空信号集
    if (sigemptyset(&emptyset) == -1) {
        perror("Error in sigemptyset");
        return 1;
    }

    // 阻塞所有信号
    if (sigprocmask(SIG_BLOCK, &set, &oldset) == -1) {
        perror("Error in sigprocmask - SIG_BLOCK");
        return 1;
    }
    
    // 打印信号集状态
    printf("Current signal set is blocked.\n");

    // 恢复信号屏蔽
    if (sigprocmask(SIG_SETMASK, &oldset, NULL) == -1) {
        perror("Error in sigprocmask - SIG_SETMASK");
        return 1;
    }

    // 打印信号集状态
    printf("Original signal set restored.\n");

    return 0;
}

运行结果如下:

3  sigaddset、sigdelset向信号集中添加/删除信号

sigaddset()sigdelset() 也是用于操作信号集的函数,允许向信号集中添加或删除特定的信号,函数原型如下:

#include <signal.h>

int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
  • set: 指向信号集。
  • signum: 需要添加/删除的信号。
  • 返回值: 成功返回 0;失败将返回-1,并设置 errno。

下面是一个简单的示例,演示如何使用 sigaddset()sigdelset()

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

int main() 
{
    sigset_t set;

    // 初始化信号集为空
    if (sigemptyset(&set) == -1) {
        perror("sigemptyset");
        return 1;
    }

    // 添加SIGINT(通常用于处理Ctrl+C中断)到信号集
    if (sigaddset(&set, SIGINT) == -1) {
        perror("sigaddset");
        return 1;
    }

    // 打印信号集状态,确认SIGINT已添加
    if (sigismember(&set, SIGINT)) {
        printf("SIGINT is in the signal set.\n");
    }

    // 从信号集中删除SIGINT
    if (sigdelset(&set, SIGINT) == -1) {
        perror("sigdelset");
        return 1;
    }

    // 再次打印信号集状态,确认SIGINT已被删除
    if (!sigismember(&set, SIGINT)) {
        printf("SIGINT is no longer in the signal set.\n");
    }

    return 0;
}

程序首先使用 sigemptyset() 创建了一个空的信号集,然后使用 sigaddset() 向信号集中添加了 SIGINT 信号,通过 sigismember() 检查 SIGINT 是否成功添加到信号集中,并打印状态信息。接着使用 sigdelset() 删除了 SIGINT 信号,并再次检查信号集状态,确认 SIGINT 已被删除。运行结果乳香

4 sigismember函数测试信号是否在信号集中

使用 sigismember()函数可以测试某一个信号是否在指定的信号集中,函数原型如下所示:

#include <signal.h>

int sigismember(const sigset_t *set, int signum);
  • set: 指定信号集。
  • signum: 需要进行测试的信号。
  • 返回值: 如果信号 signum 在信号集 set 中,则返回 1;如果不在信号集 set 中,则返回 0;失败则返回-1,并设置 errno。

以下是一个使用 sigismember() 的示例代码:

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

int main() 
{
    sigset_t set;

    // 初始化信号集,包含所有信号
    if (sigfillset(&set) == -1) {
        perror("sigfillset");
        return 1;
    }

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

    return 0;
}

程序首先使用 sigfillset() 填充信号集 set,使其包含所有可能的信号。然后使用 sigismember() 检查 SIGINT是否是信号集的成员,并打印相应的信息。运行结果如下:

 

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

几度春风里

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值