• 使用sigprocmask函数阻塞SIGQUIT信号


    1 相关函数介绍

    1.1 信号集函数

    sigset_t表示一个信号集,如下为5个处理信号集的函数:

    1. #include
    2. //成功返回0,出错返回-1
    3. int sigemptyset(sigset_t *set);
    4. //成功返回0,出错返回-1
    5. int sigfillset(sigset_t *set);
    6. //成功返回0,出错返回-1
    7. int sigaddset(sigset_t *set, int signo);
    8. //成功返回0,出错返回-1
    9. int sigdelset(sigset_t *set, int signo);
    10. //成功返回1,出错返回0
    11. int sigismember(const sigset_t *set, int signo);

    sigemptyset用来初始化set指向的信号集,清除其中所有信号。
    sigfillset用来初始化set指向的信号集,使得其包含所有信号。
    sigaddset用来添加一个信号到信号集中。
    sigdelset用来从信号集中删除一个信号。

    1.2 sigprocmask函数

    一个进程的信号屏蔽字规定了当前阻塞而不能递送给该进程的信号集。
    函数sigprocmask可以检测或更改进程的信号屏蔽字。

    1. #include
    2. //成功返回0,出错返回-1
    3. int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);

    若oset是非空指针,那么当前信号屏蔽字通过oset返回。
    若set是非空指针,则参数how表示如何修改当前信号屏蔽字;若set是空指针,则how无意义。

    how

    说明

    SIG_BLOCK

    该进程新的信号屏蔽字是当前信号屏蔽字和set指向信号集的并集。

    set包含了希望阻塞的附加信号。

    SIG_UNBLOCK

    该进程新的信号屏蔽字是当前信号屏蔽字和set指向信号集补集的交集。

    set包含了希望解除的附加信号。

    SIG_SETMASK

    该进程新的信号屏蔽字是set指向的值。

    SIG_BLOCK是或操作。SIG_SETMASK是赋值操作。
    注意,不能阻塞SIGKILL和SIGSTOP信号。
    在调用sigprocmask后如果有不再阻塞的信号,则在sigprocmask返回前,至少将其中之一递送给该进程。
    sigprocmask是仅为单线程进程定义的。

    1.3 sigpending函数

    sigpending函数返回一信号集,对于调用进程而言,其中的各信号是阻塞不能递送的,因而一定是当前未决的。

    1. #include
    2. int sigpending(sigset_t *set);

    即查下当前哪些信号是阻塞的。

    2 使用sigprocmask函数阻塞SIGQUIT信号

    如下进程会阻塞SIGQUIT信号,休眠5s。然后不再阻塞SIGQUIT信号,休眠5s。

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. static void sig_quit(int);
    7. int main(void)
    8. {
    9. sigset_t newmask, oldmask, pendmask;
    10. if (signal(SIGQUIT, sig_quit) == SIG_ERR)
    11. printf("can't catch SIGQUIT");
    12. //1 Block SIGQUIT and save current signal mask.
    13. sigemptyset(&newmask);
    14. sigaddset(&newmask, SIGQUIT);
    15. if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
    16. printf("SIG_BLOCK error");
    17. sleep(5); //2 SIGQUIT here will remain pending
    18. if (sigpending(&pendmask) < 0)
    19. printf("sigpending error");
    20. if (sigismember(&pendmask, SIGQUIT))
    21. printf("\nSIGQUIT pending\n");
    22. //3 Restore signal mask which unblocks SIGQUIT.
    23. printf("SIGQUIT unblocked >>>\n");
    24. if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
    25. printf("SIG_SETMASK error");
    26. printf("SIGQUIT unblocked <<<\n");
    27. sleep(5); //4 SIGQUIT here will terminate with core file
    28. exit(0);
    29. }
    30. static void sig_quit(int signo)
    31. {
    32. printf("caught SIGQUIT -------\n");
    33. if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) //使SIGQUIT信号恢复默认行为(退出+core)
    34. printf("can't reset SIGQUIT");
    35. }

    操作1:在第一次休眠5s内产生一次SIGQUITI信号(ctrl+\),在第二次休眠5s内产生一次SIGQUIT信号(ctrl+\)。
    测试1结果如下:

    1. ^\SIGQUIT pending
    2. SIGQUIT unblocked >>>
    3. caught SIGQUIT -------
    4. SIGQUIT unblocked <<<
    5. ^\ 退出(核心已转储)

    在第一次休眠5s内产生的SIGQUIT信号,这时信号是未决的,在sigprocmask解除block后,SIGQUIT信号不再被阻塞,立刻被递送到调用进程,
    信号处理函数sig_quit捕捉到SIGQUIT后,按照自定义处理,处理完后使SIGQUIT信号恢复为默认行为(退出+core)。

    操作2:在第一次休眠5s内产生多次SIGQUITI信号(ctrl+\),在第二次休眠5s内产生一次SIGQUIT信号(ctrl+\)。
    测试2结果如下:

    1. ^\^\^\^\^\
    2. SIGQUIT pending
    3. SIGQUIT unblocked >>>
    4. caught SIGQUIT -------
    5. SIGQUIT unblocked <<<
    6. ^\ 退出(核心已转储)

    在第一次休眠5s内产生多个SIGQUIT信号,从结果来看,只有一个信号会递送给调用进程。

  • 相关阅读:
    RKE2 config containerd private registry (rke2配置私有仓库地址)
    前端知识学习案例10-开发企业网站10-实现案例部分1
    石油、化工 工程上都在用的地下管线探测仪---TFN A1200
    2022年全球市场锁相放大器模块总体规模、主要生产商、主要地区、产品和应用细分研究报告
    菜鸟打印组件系列-vue3快速接入
    安装系统出现dracut-initqueue状态
    导入导出问题
    Linux高性能服务器编程——ch8笔记
    MVC 、MVP、MVVM
    实时车辆行人多目标检测与跟踪系统(含UI界面,Python代码)
  • 原文地址:https://blog.csdn.net/u012906122/article/details/126442680