《UNIX环境高级编程》笔记--sigsuspend函数

2024-04-14 21:58

本文主要是介绍《UNIX环境高级编程》笔记--sigsuspend函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

更改进程的信号屏蔽字可以阻塞所选择的信号,或解除对它们的阻塞,使用这种技术可以保护不希望由信号中断的代码临界区。

如果希望对一个信号解除阻塞,然后pause等待以前被阻塞的信号发生,将如何呢?假定信号是SIGINT,实现这一点的一种

不正确的方法是:

sigset_t  newmask,oldmask;
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0){perror(sigprocmask);return -1;
}
//执行其他的操作
if(sigprocmask(SIG_SETMASK &oldmask, NULL) < 0){perror(sigprocmask);return -1;
}
pause();
如果在信号阻塞时将其发送给进程,那么该信号的传递就被推迟直到对它解除了阻塞。对应用程序而言,该信号好像发生解除

对SIGINT的阻塞和pause之间,如果发生了这种情况,后者如果在解除阻塞时刻和pause之间确实发生了信号,那么就出现了

问题,我们可能不会再见到该信号,这样使得pause永远阻塞。

为了纠正此问题,需要在一个原子操作中恢复信号屏蔽字,然后使进程休眠。这种功能由sigsuspend函数提供。

#include <signal.h>
int sigsuspend(const sigset_t *sigmask);  //返回值为-1,并将errno设置为EINTR。

将进程的信号屏蔽字设置为由sigmask指向的值。在捕捉到一个信号或发生了一个会终止该进程的信号之前,该进程被挂起。

如果捕捉到一个信号而且从该信号处理层序返回,则sigsuspend返回,并且将该进程的信号屏蔽字设置为调用sigsuspend之

前的值。


实践:

#include <stdio.h>
#include <signal.h>static void sig_int(int);int main(void){sigset_t newmask,oldmask,waitmask;printf("program start.\n");if(signal(SIGUSR1, sig_int) == SIG_ERR){perror("signal");return -1;}if(signal(SIGUSR2, sig_int) == SIG_ERR){perror("signal");return -1;}sigemptyset(&waitmask);sigaddset(&waitmask, SIGUSR1);sigemptyset(&newmask);sigaddset(&newmask, SIGUSR2);if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0){perror("sigprocmask");return -1;}printf("in critical region.\n");sigsuspend(&waitmask);if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0){perror("sigprocmask");return -1;}printf("program exit.\n");return 0;
}static void sig_int(int signo){printf("int sig_int:%d.\n",signo);
}
运行结果:

[root@yanPC apue]# ./a.out &
[1] 16802
program start.
in critical region.
[root@yanPC apue]# kill -SIGUSR1 16802
[root@yanPC apue]# kill -SIGUSR2 16802
int sig_int:12.
int sig_int:10.
program exit.

一开始设置对SIGUSR2进行阻塞,当程序执行了sigsuspend后,使用waitmask,即对SIGUSR1进行阻塞,对SIGUSR2

解除阻塞,所以向进程发送SIGUSR1后没有响应,向进程发送SIGUSR2后,执行sig_int函数, sigsuspend函数返回,

并且将mask设置成调用sigsuspend之前的状态,即不会对SIGUSR1阻塞,所以执行了sig_int函数。

这篇关于《UNIX环境高级编程》笔记--sigsuspend函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/904133

相关文章

Python中你不知道的gzip高级用法分享

《Python中你不知道的gzip高级用法分享》在当今大数据时代,数据存储和传输成本已成为每个开发者必须考虑的问题,Python内置的gzip模块提供了一种简单高效的解决方案,下面小编就来和大家详细讲... 目录前言:为什么数据压缩如此重要1. gzip 模块基础介绍2. 基本压缩与解压缩操作2.1 压缩文

Python内置函数之classmethod函数使用详解

《Python内置函数之classmethod函数使用详解》:本文主要介绍Python内置函数之classmethod函数使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 类方法定义与基本语法2. 类方法 vs 实例方法 vs 静态方法3. 核心特性与用法(1编程客

Python函数作用域示例详解

《Python函数作用域示例详解》本文介绍了Python中的LEGB作用域规则,详细解析了变量查找的四个层级,通过具体代码示例,展示了各层级的变量访问规则和特性,对python函数作用域相关知识感兴趣... 目录一、LEGB 规则二、作用域实例2.1 局部作用域(Local)2.2 闭包作用域(Enclos

MySQL count()聚合函数详解

《MySQLcount()聚合函数详解》MySQL中的COUNT()函数,它是SQL中最常用的聚合函数之一,用于计算表中符合特定条件的行数,本文给大家介绍MySQLcount()聚合函数,感兴趣的朋... 目录核心功能语法形式重要特性与行为如何选择使用哪种形式?总结深入剖析一下 mysql 中的 COUNT

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

MySQL 中 ROW_NUMBER() 函数最佳实践

《MySQL中ROW_NUMBER()函数最佳实践》MySQL中ROW_NUMBER()函数,作为窗口函数为每行分配唯一连续序号,区别于RANK()和DENSE_RANK(),特别适合分页、去重... 目录mysql 中 ROW_NUMBER() 函数详解一、基础语法二、核心特点三、典型应用场景1. 数据分

SQLite3 在嵌入式C环境中存储音频/视频文件的最优方案

《SQLite3在嵌入式C环境中存储音频/视频文件的最优方案》本文探讨了SQLite3在嵌入式C环境中存储音视频文件的优化方案,推荐采用文件路径存储结合元数据管理,兼顾效率与资源限制,小文件可使用B... 目录SQLite3 在嵌入式C环境中存储音频/视频文件的专业方案一、存储策略选择1. 直接存储 vs

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

Java中的for循环高级用法

《Java中的for循环高级用法》本文系统解析Java中传统、增强型for循环、StreamAPI及并行流的实现原理与性能差异,并通过大量代码示例展示实际开发中的最佳实践,感兴趣的朋友一起看看吧... 目录前言一、基础篇:传统for循环1.1 标准语法结构1.2 典型应用场景二、进阶篇:增强型for循环2.

Python get()函数用法案例详解

《Pythonget()函数用法案例详解》在Python中,get()是字典(dict)类型的内置方法,用于安全地获取字典中指定键对应的值,它的核心作用是避免因访问不存在的键而引发KeyError错... 目录简介基本语法一、用法二、案例:安全访问未知键三、案例:配置参数默认值简介python是一种高级编