小工具知识网

当前位置: 首页 > 行业知识 > Linux-信号2

行业知识

Linux-信号2

2026-10-30 14:38:34 来源:互联网转载

文章目录

  • 前言
  • 一、信号是如何保存的?
    • int sigemptyset(sigset_t *set);
    • int sigfillset(sigset_t *set);
    • int sigaddset (sigset_t *set, int signo);
    • int sigdelset(sigset_t *set, int signo);
    • int sigismember(const sigset_t *set, int signo);
    • int sigpending(sigset_t *set);
    • int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
      • 1.SIG_BLOCK
      • 2.SIG_UNBLOCK
      • 3.SIG_SETMASK
      • 二、学习步骤
        • 我们提出三个问题并对问题进行一一解答来进行我们的学习
          • 问题1. 如果我们将一个***循环进程的所有信号都捕捉,是不是该进程无法被退出?
          • 问题2. 如果我们将一个信号block阻塞,并发送对应信号,pending表的对应该信号bit位是不是由0置1?
          • 问题3. 如果我们将一个***循环进程的所有信号都阻塞,是不是该进程也无法被退出?
          • 1.解答问题1
          • 2.解答问题2
          • 3.解���问题3

            前言

            上节课我们学习了信号产生到处理过程的现象以及信号的捕捉,这节课主要学习信号的保存。

            我们需要熟练使用以下函数

            #include

            int sigemptyset(sigset_t *set);

            int sigfillset(sigset_t *set);

            int sigaddset (sigset_t *set, int signo);

            int sigdelset(sigset_t *set, int signo);

            int sigismember(const sigset_t *set, int signo);

            int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

            int sigpending(sigset_t *set);


            一、信号是如何保存的?

            上节课我们说过,信号是在进程的PCB中存储 信号的位图,而实际上,可不止有一个表(位图)。

            block信号集是用以保存被block阻塞的信号,一般被称为信号屏蔽字(阻塞信号集),pending信号集就是我们上节课所说的那个收到信号即相对位由0置1的位图,一般被称为未决信号集。

            对于阻塞,这是提前预设好的,目的是为了让该进程屏蔽该信号,所以如果一个信号被阻塞,而又收到了该信号,虽然pending信号集由0置1,但是不进行delivery(信号递达:信号递达操作即信号的处理)操作。

            而这两个信号集,在我们看来理解其实就是位图,但是OS将他们封装成了自定义类型sigset_t,通过这样的封装,对于我们用户就无法随心所欲地更改其信号集的数据,只能通过OS提供给我的系统接口函数。

            现在来认识一下系统交给我们的一些接口函数。

            int sigemptyset(sigset_t *set);

            函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含 任何有

            效信号。

            成功返回0,出错返回-1

            int sigfillset(sigset_t *set);

            函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示 该信号集的有效信号包括系

            统支持的所有信号。

            成功返回0,出错返回-1

            int sigaddset (sigset_t *set, int signo);

            函数sigaddset用于将set所指向的信号集的signo信号置位。

            成功返回0,出错返回-1

            int sigdelset(sigset_t *set, int signo);

            函数sigdelset用于将set所指向的信号集的signo信号置零。

            成功返回0,出错返回-1

            int sigismember(const sigset_t *set, int signo);

            函数sigismember用于判断set所指向信号集的signo信号是否为1。

            是则返回1,否则为0。

            int sigpending(sigset_t *set);

            函数sigpending用于读取当前进程的未决信号集,通过set参数传出。

            调用成功则返回0,出错则返回-1。

            int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

            函数sigprocmask用于更改block信号集,参数how为选项,该函数提供三种选项

            1.SIG_BLOCK

            该选项是希望在目前的信号屏蔽字添加set信号集的有效信号,相当于mask=mask|set

            2.SIG_UNBLOCK

            该选项是希望在目前的信号屏蔽字去除set信号集的有效信号,相当于mask=mask&(~set)

            3.SIG_SETMASK

            该选项就比较暴力些,相当于mask=set

            而参数oset为输出型参数,用于保存老信号集。

            需要注意的,在使用sigset_ t类型的变量之前,一定要调 用sigemptyset或sigfillset做初始化,使信号集处于确定的

            状态。

            二、学习步骤

            我们提出三个问题并对问题进行一一解答来进行我们的学习

            问题1. 如果我们将一个***循环进程的所有信号都捕捉,是不是该进程无法被退出?

            问题2. 如果我们将一个信号block阻塞,并发送对应信号,pending表的对应该信号bit位是不是由0置1?

            问题3. 如果我们将一个***循环进程的所有信号都阻塞,是不是该进程也无法被退出?

            1.解答问题1

            代码如下(示例):

            #include#include#include#includevoid catchSig(int signum){    std::cout     for(int i = 1; i         signal(i,catchSig);    }    while(1)    {        std::cout     for (int i = 1; i         // 通过sigismember来打印我们的pending信号集        std::cout     sigset_t set;    sigset_t block;    sigset_t oset;    // 1.进行初始化    sigemptyset(&set);    sigemptyset(&block);    sigemptyset(&oset);    // 2.阻塞2号信号    sigaddset(&block, 2);    sigprocmask(SIG_BLOCK, &block, &oset);    std::cout         // 3.1 获取当前的未决信号集        sigpending(&set);        ShowSet(set);        sleep(1);    }    return 0;}    for (int i = 1; i         // 通过sigismember来打印我们的pending信号集        std::cout     if ((signum != 19) &&(signum != 9) && signum     sigset_t set;    sigset_t block;    sigset_t oset;    // 1.进行初始化    sigemptyset(&set);    sigemptyset(&block);    sigemptyset(&oset);    // 2.阻塞所有信号    for (int i = 1; i         sigaddset(&block, i);    }    sigprocmask(SIG_SETMASK, &block, &oset);    // 3.循环打印未决信号集    int count = 1;    while (1)    {        // 3.1 获取当前的未决信号集        sigpending(&set);        ShowSet(set);        SendSig(count++);        sleep(1);    }    return 0;}

上一篇:鹅蛋腌制后的处理秘诀,美食保存与烹饪方法全解析!

下一篇:监控主机状态指示灯是红灯吗怎么回事