搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
2023面试高手
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
模电学习笔记(3)_模电中ubq和ubeq
2
当运行深度学习网络出现cuda out of memory错误:_cuda oom
3
Kafka科普系列 | 什么是LSO?_kafka lso
4
[回忆]2007年的GDNT研发广东北电辞职信._广东北电通信设备有限公司
5
Solidity实现智能合约——Solidity高级理论(三)_智能合约& 线上 ide 实现 solidity 合约
6
【2023】kafka入门学习与使用(kafka-2)
7
手把手做一个公众号GPT智能客服(七)GPT 接入微信机器人_gpt接入企业微信客服
8
NLP-预训练模型:综述【基础:BERT】【预训练任务优化:ERNIE、SpanBERT】【训练方法优化:RoBERTa、T5】【模型结构优化:XLNet、ALBERT、ELECTRA】【模型轻量化】_t5, roberta, albert,bert,transformer,macbert区别
9
python列表求平均值函数_计算给定列表中所有元素的平均值(定义一个函数)
10
PyTorch深度学习入门笔记(八)神经网络的基本骨架 nn.Module的使用_class net(torch.nn.module)
当前位置:
article
> 正文
linux 信号阻塞和信号未决_linux信号阻塞作用
作者:2023面试高手 | 2024-03-31 06:24:13
赞
踩
linux信号阻塞作用
信号的“未决”是一种状态,指的是从信号的产生到信号被处理前的这一段时间;
信号的“阻塞”是一个开关动作,指的是阻止信号被处理,但不是阻止信 号产生。
信号的阻塞就是让系统暂时保留信号留待以后发送。由于另外有办法让系统忽略信号,所以一般情况下信号的阻塞只是暂时的,只是为了 防止信号打断敏感的操作。
* 当你需要修改某些全局变量时,你可以通过sigprocmask()函数阻塞处理函数中也使用该变量的信号。
* 在某些信号处理函数中,为了阻止同类信号的到来,可以使用sigaction()函数的sa_mask阻塞特定的信号。
11.7.1 阻塞信号的作用
使用函数sigprocmask()阻塞信号的传递,只是延迟信号的到达。信号会在解除阻塞后继续传递。这种情况往往需要在信 号程序和其它程序共享全局变量时,如果全局变量的类型不是sig_atomic_t类型,当一部分程序恰好读、写到变量的一半发生信号,而信号程序里会改 变该信号,那么就会产生混乱。为了避免这种混乱,提供程序的可靠性,你必须在操作这类变量前阻塞信号,操作完成后恢复信号的传递。
信号阻塞也 用来处理必须保证连续操作的完整性方面。比如,你需要检测一个标志(可以是sig_atomic_t类型),该标志在信号程序中设置,当标志没有设置时可 以执行某个操作。假如恰好在检测标志后发生信号,那么信号返回后,程序也会执行这个操作,即使已经设置了标志。这显然会引起程序的不稳定。最好的方法就是 在检测标志到执行操作之间阻塞信号的发生。
11.7.2 信号集
所有的信号阻塞函数都使用称作信号集的数据结构来表明受到影响的信号。每一个操作都包括两个阶段:创建信号集,传递信号集给特定的库函数。下面说明信号集 和相关的数据类型:
sigset_t:这个数据类型用来代表信号的集合,有两种方法对它进行初始化。一种是通过函数 sigemptyset()使之不包含任何信号,然后用sigaddset()函数加入需要的信号。另一种方法是通过函数sigfillset()使之包 含所以信号,然后通过sigdelset()函数删除我们不需要的信号。注意,千万不用试图通过手工方式直接操作这种类型变量,否则会带来严重的错误。下 面介绍相关的函数。
int sigemptyset(sigset_t *set):初始化信号集set使之不包含任何信号,这个函数总是返回0。
int sigfillset(sigset_t *set):初始化信号集set使之包含所有的信号,这个函数也是总返回0。
int sigaddset(sigset_t *set, intsignum):该函数把信号signum加入到信号集set中,需要注意的是这个函数只是修改了set变量本身,并不作其它操作。该函数成功操作 返回0,失败返回-1,错误代码设置成EINVAL,表示signum不是有效的信号代码。
int sigdelset(sigset_t *set, int signum):该函数从信号集set中删除信号signum,其它方面和sigaddset()函数类似,不再赘述。
int sigismember(const sigset_t *set,intsignum):这个函数测试信号signum是否包含在信号集合set中,如果包含返回1,不包含返回0,出错返回-1。错误代码也只 有一个EINVAL,表示signum不是有效的信号代码。
11.7.3 进程的信号掩码
我们称正在阻塞的信号的集合为信号掩码(signal mask)。每个进程都有自己的信号掩码,创建子进程时子进程将继承父进程的信号掩码。我们可以通过修改当前的信号掩码来改变信号的阻塞情况。
int sigprocmask(int how, const sigset_t *set,sigset_t *oldset),该函数用来检查和改变调用进程的信号掩码,其中的how参数指出信号掩码改变的方式,必须是下面的值之一:
SIG_BLOCK,阻塞set中包含的信号。意思是说把set中的信号加到当前的信号掩码中去,新的信号掩码是set和旧信号掩码的并集。
SIG_UNBLOCK,解除set中信号的阻塞,从当前信号掩码中去除set中的信号。
SIG_SETMASK,设置信号掩码,既按照set中的信号重新设置信号掩码。
最后一个参数是进程原来的信号集。如果你只需要改变信号的阻塞情况而不需要关心原来的值,可以传递NULL指针给函数。如果你希望什么也不改变,只是想获 得当前信号掩码的信息,那么把set设置成NULL,old中返回当前的设置。
sigprocmask()函数成功返回0,失败返回-1。失败时错误代码只可能是EINVAL,表示参数how不合法。
不能阻塞 SIGKILL和SIGSTOP等信号,但是当set参数包含这些信号时sigprocmask()不返回错误,只是忽略它们。另外,阻塞SIGFPE这 样的信号可能导致不可挽回的结果,因为这些信号是由程序错误产生的,忽略它们只能导致程序无法执行而被终止。
11.7.4 举例:禁止关键代码时信号到达
假定你建立信号SIGALRM的处理函数,在其中设置一个标志。主程序中检查标志并清除,使用函数sigprocmask()控制信号到达:
#include
volatile sig_atomic_t flag=0;
int
main(void)
{
sigset_t block_alarm;
... ...
sigemptyset(&block_alarm);
sigaddset(&block_alarm,SIGALRM);
while(1)
{
sigprocmask(SIG_BLOCK,&block_alarm,NULL);
if(flag)
{
... ...
flag=0;
}
sigprocmask(SIG_UNBLOCK,&block_alarm,NULL);
... ...
}
}
11.7.5 在信号句柄中阻塞信号
信号句柄执行时,如果你希望从头至尾不会被其它信号打扰,那么你必须阻塞其它信号。当一个信号句柄激活时,相同的信号自动被阻塞,但是其它信号并不会阻 塞,最可靠的方法是使用sigaction结构的sa_mask成员。例如:
#include
#include
void catch_stop();
void
install_handler(void)
{
struct sigaction setup_action;
sigset_t block_mask;
sigemptyset(&block_mask);
sigaddset(&block_mask,SIGINT);
sigaddset(&block_mask,SIGQUIT);
setup_action.sa_handler=catch_stop;
setup_action.sa_mask=block_mask;
setup_action.sa_flag=0;
sigaction(SIGINT,&setup_action,NULL);
}
这个方法比在信号函数中使用 sigprocmask()函数可靠,因为使用sigprocmask()函数起码无法避免在信号函数开始的信号不被阻塞的间隙。使用这个机制你不能从当 前信号掩码中删除信号,但是,在信号函数当中,你可以使用sigprocmask()阻塞信号。在任何情况下,信号句柄返回时,系统重新装入进入信号句柄 之前的信号掩码。当信号句柄一返回,信号句柄执行时被阻塞的信号就会立即到达,甚至在返回被中断的代码前就要进入新的信号处理句柄。
11.7.6 查找阻塞的信号
你能够使用函数sigpending()来查找系统中何种信号有正在被阻塞的信号。
int sigpending(sigset_t *set),该函数把存在阻塞信号的信号类型放置到set中,可以使用sigismenber()函数判断某种信号是否是set的成员。该函数成功返回 0,失败返回-1。
下面举例说明:
#include
#include
sigset_t base_mask,wait_mask;
sigemptyset(&base_mask);
sigaddset(&base_mask,SIGINT);
sigaddset(&base_mask,SIGTSTP);
sigprocmask(SIG_SETMASK,&base_mask,NULL);
... ...
sigpending(&waiting_mask);
if(sigismember(&waiting_mask,SIGINT))
{
//do something, if user try killing the process
}
else if(sigismember(&waiting_mask,SIGTSTP))
{
//user tring to stop process
}
对于同一种信号,如果有被阻塞的信号存在,那么其它到来的信号就会被丢弃,而不是被阻塞。
11.7.7 信号阻塞的代替方法
我们可以采用在信号处理程序中读取其它程序进入关键代码前设置的标志来判断是否进行处理,如果不能进行处理,则在一个公共变量中设置不能进行处理的信号的 值,关键代码执行完成后再重新发送该信号,请看下面的例子:
volatile sig_atomic_t signal_pending;
volatile sig_atomic_t defer_signal;
void
handler(int signum)
{
if(defer_signal)
signal_pending=signum;
else
...
}
...
void
update_number(int frob)
{
defer_signal++;
...
defer_signal--;
if(defer_signal==0&&signal_pending!=0)
raise(signal_pending);
}
信号是unix处理异步事件的经典方法。产生信号的方法一般有:
用户按中断键、硬件异常信号、软件异常信号、用户的kill命令等。系统也可以有多种方式处理这些异步 事件,比如:忽略信号、捕捉信号或者执行默认动作。
大多数unix程序都是用信core文件来检查进程终止时候的状态的。 core文件就是对于该文件的进程存储映像进行复制。
一定要记住这两种情况:
1)当进程启动的时候,所有信号的状态就是系统默认或者忽略。除非调用exec动作。
因为exec动作,将原先设置为要捕捉的信号为默认动作,道理很简单,就是exec要用新的进程地址空间覆盖旧的,自然原先的信号就已经被屏蔽了。
2)开启一个子进程的时候,子进程继承父进程的信号处理方式。因为子进程一开始启动就复制了父进程的存储映像,信号捕捉函数地址在父子进程中都是有意义 的。
signal的信号处理方式带有好多的缺陷,比如,在产生信号和调用signal信号处理程序之间有一个时 间窗口,如果再来一个信号可能丢失。等等。
在执行慢速的系统调用的时候,进程很可能阻塞几个小时或者数天,如果进程在执行一个低速系统调用期间捕捉到 一个信号的时候,那么该系统调用就被中断不在继续执行。因为一个信号发生了,这就意味着发生了某种事情,所以这是唤醒被阻塞的进程的好机会。
为了帮助应用进程不必处理被总段的系统调用,linux系统引入了某些被中断系统调用的自动重启函 数,包括:Ioctl,read,readv,write,writev,wait和waitpid。前5个只对低速设备调用才有效,而后两个只对捕捉到 进程退出信号时才有效。可重入函数主要用于多任务环境中,一个函数是可重入与否,简单的说就是否可以被中断。假如一个链表,如果被中断则会发生莫名的错误,其执行序列是不可预测的。
信号发生的时候到递送之间的时间间隔,我们称为信号时未决的。在未决的信号期间,如果我们阻塞了某些信号,那么,即使我们产生信号,这些都会被阻塞。除非 等解除阻塞以后,系统才会处理这些信号。而且,阻塞期间多次产生的同一个信号,解除阻塞后,系统处理且只处理一次。
引用原文:
1. http://www.hadoopor.com/redirect.php?tid=1156&goto=lastpost
2. http://www.groad.net/bbs/read.php?tid-920.html
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/2023面试高手/article/detail/343385
推荐阅读
article
【
Linux
&
Nginx
】
Linux
下
安装
Nginx
与
版本升级
(
nginx
-
1.24
.0)_ng...
虽然有了selinux,我们的系统会更安全,但是对于我们的学习
Nginx
的历程中,会多很多设置,所以这块建议大家将sel...
赞
踩
article
Ubuntu
Linux
18.10下面安装魔法门之
英雄无敌
3_
heroes
.of.
might
.an...
不废话,直接进入正题:1.Heroes.of.Might.
and
.Magic.3.
Linux
.[mulek.info]....
赞
踩
article
在
linux
下
运行
英雄,在
Linux
下
玩《
英雄无敌
3
》游戏...
下
面就是我要讲的主要部分,怎么对补丁进行hack。用vim打开heroes
3
-1.
3
.1-x86.run,搜索 +6 ,...
赞
踩
article
Nvidia
Tesla A100显卡
驱动
安装
下载
(
Linux
)_
nvidia
-
smi
下载
...
关于本人最近
安装
nvidia
显卡的总结和一些坑 centos71.查看
Linux
系统是否已经
安装
了
Nvidia
驱动
命令行...
赞
踩
article
ubuntu
linux
下面运行《暗黑
破坏神
2
》和
英雄无敌
3-死亡阴影_死亡阴影
linux
...
游戏文件:https://pan.baidu.com/s/114laDvxfEzpmvFEApg1yIQ#list/pa...
赞
踩
article
Ubuntu
/
Linux
安装
Android
-
sdk
和
commandlinetools
_comm...
安装 android-
sdk
-
linux
和
sdk
manager,以及配置步骤。并生成licenses _comman...
赞
踩
article
linux
dp
接口
显示,
ubuntu
dp
接口
支持...
帖子1:
ubuntu
我禁用了Nouveau 驱动以后, 页面显示正常, 我也就没用再安装n卡驱动. 怎么查看现在显卡...
赞
踩
article
linux
-
y
参数 的用处
_-
y
命令
详解...
命令
后面加上 -
y
后,当执行该
命令
后,出现 需要选择确认或取消的时候,(即选择
y
/n的时候),自动选择
y
_-
y
命令
详...
赞
踩
article
L
in
ux
常用命令
与教程_
case
$
verify
in
[yy][ee][
ss
]|[yy]) u...
全拼GlobalsearchREgularexpre
ss
ionandPr
in
toutthel
in
e.作用文本搜索工具,根...
赞
踩
article
Linux
-
ubuntu
系统查看
显卡
型号、
显卡
信息
详解
_
ubuntu
查询
显卡
信息
...
lspci | grep -i vga#----output------01:00.0 VGA compatible c...
赞
踩
article
Linux
(
Ubuntu
)系统
查看
显卡
型号
_
linux
查看
机器
显卡
id...
Linux
(
Ubuntu
)系统
查看
显卡
型号
给我的
Ubuntu
安装
显卡
驱动时,需要
查看
显卡
型号
,因为我的是Windows/...
赞
踩
article
LINUX
设置LL
的
时候
显示
日期
的
格式
_
ll
不
显示
时间
...
1、临时更改
显示
样式,当回话结束后恢复原来
的
样式export TIME
_
STYLE='+%Y-%m-%d %H:%M:%...
赞
踩
article
Android
与其他
基于
Linux
的
系统
有何不同?_
android
credstore
...
文章目录一言以蔽之原文:https://embeddedbits.org/what-differs-
android
-fr...
赞
踩
article
Linux
(
Ubuntu
)下适配
Open3D
_ML库的
CUDA
环境配置_
open3d
的
linux
版本...
本文针对
Linux
不同版本内核切换、适配
CUDA
的NVIDIA显卡驱动安装、
CUDA
-cudnn-Pytorch下载安装...
赞
踩
article
相爱相杀
的
CP——初谈
Android
Kernel
与
Linux
Kernel
_
linux
kern...
当
Linux
社区决定将安卓踢出
Linux
Kernel
时,他注定犯下了一个大错。本是同根生,相煎何太急。这次我们来简单聊...
赞
踩
article
【
Android
系列
1.0
驱动
开发 ---
Linux
驱动
内核
】_android
1.0
驱动
...
参考文档Context当探索Binder机制,引出很多
Linux
相关概念。说Binder是
驱动
程序,Binder用了内存...
赞
踩
article
Lin
u
x
下
检测
是否插入U
盘
_
lin
u
x
如何
检测
u
盘
...
Lin
u
x
下
检测
是否插入U
盘
LIn
u
x根目录
下
主要常见的目录定义:/boot 开机所需文件–内核、开机菜单所需配置...
赞
踩
article
lin
u
x
下
检测
U盘
插入
并读取文件
_
imx6
u
ll
lin
u
x
u
盘
插入
检测
...
建立NET
_
LINK套接字,与内核通信实时
检测
U状态(与基本的套接字编程基本一致) #incl
u
de #incl
u
de ...
赞
踩
article
Linux
USB
设备热插拔检测...
原文链接#include
#include
#include
[详细]
-->
赞
踩
article
lin
u
x 查看
u
盘
文件
,详细介绍
Lin
u
x
系统
下检测U
盘
是不是已经连接的方法...
Lin
u
x
操作
系统
是基于Unix操作
系统
发展而来的一种克隆
系统
,它诞生于1991年的10月5日(这是第一次正式向外公布的...
赞
踩
相关标签
linux
nginx
python
运维
安全
网络安全
网络
在linux下运行英雄
centos
android
ubuntu
linux dp接口显示
bash
总结
Linux(Ubuntu)
CUDA
cudnn
pytorch
Open3D_ML