您的位置:首页 > 房产 > 建筑 > 衡阳疫情v_中国民主促进会网站_网站关键词如何优化上首页_百度公司排名多少

衡阳疫情v_中国民主促进会网站_网站关键词如何优化上首页_百度公司排名多少

2025/5/7 8:29:27 来源:https://blog.csdn.net/2303_80828380/article/details/145938053  浏览:    关键词:衡阳疫情v_中国民主促进会网站_网站关键词如何优化上首页_百度公司排名多少
衡阳疫情v_中国民主促进会网站_网站关键词如何优化上首页_百度公司排名多少

目录

一、信号的保存:

二、内核中的信号表示:

handler:

pending:

block:

sigset_t:

sigprocmask:

sigpending:

应用:


一、信号的保存:

当我们信号产生后,并不会立即处理这个信号,而是有一段时间窗口,在这个时间窗口内,信号没有被处理,而是保存起来了,那么进程是怎样保存对应的信号的呢?

我们知道,一定是OS给进程发送信号的,并且这个信号肯定是在我们进程的PCB中,所以在进程的PCB中就一定有一个变量来存放信号,这个变量就是一个整数int,当然,我们不能够仅仅看到这个整数,更要看到的是这是一个位图结构:

1、比特位的内容是1就证明着当前进程接受到了信号
2、第几个比特位被修改位1,就证明收到了几号信号

3、那么OS向进程发送信号的本质就是OS修改PCB中,对应信号的位图结构的对应比特位,所以OS发信号就是首先找到进程里面描述信号的字段,然后将对应的比特位的位置修改为1

当OS向我们的进程发送多个相同信号的时候,并不会处理很多次,只会执行一次(这就相当于当我们在打游戏的时候,同时妈妈喊我们吃饭,会喊很多次,但是我们仅仅只会最后执行一次),毕竟位图只有0和1的结构,但是以上是对于普通信号的,如果是实时信号,那么发送了几次就要执行几次,是采用的是队列数据结构进行管理的

接下来了解关于信号的新概念:

信号产生:由上一篇文章所讲的几种产生方式

信号递达:实际执行信号的处理动作

信号未决:信号从产生到递达之间的状态

信号阻塞:也可叫做信号屏蔽,可随时屏蔽阻塞,并且在解除屏蔽之前都无法进行信号处理

当信号递达了就会有3种处理方式:
默认处理(SIG_DFL),忽略(SIG_IGN),自定义动作(handler)

二、内核中的信号表示:

如上,每一个进程都维护着如上的三张表,分别是block,pending和handler,其中block和pending表都是位图结构的,handler就是处理方式,这三张表是要横着看的

handler:

handler表就是当信号递达1时的处理方式,这是一个有着31个成员的函数指针数组(我们只考虑普通信号,所以也就是只有31个位置)格式为:返回值为空,参数为int的函数

如下是源码:

/* Type of a signal handler.  */
typedef void (*__sighandler_t) (int);/* Fake signal functions.  */
#define SIG_ERR	((__sighandler_t) -1)		/* Error return.  */
#define SIG_DFL	((__sighandler_t) 0)		/* Default action.  */
#define SIG_IGN	((__sighandler_t) 1)		/* Ignore signal.  */

如上,这个handler表的自定义中就是使用signal()函数重新设定对应的动作

pending:

当pending中的对应信号的值为1就证明这个信号是处于未决状态,所以如何记录已经产生的信号? ----- 将pending表中的对应的比特位置为1即可

所以pending表中存放的就是该信号产生到未处理的过程中的信号,这就是未决状态,

其实,我们信号的实现,是模拟的我们的硬件中断,这里的pinding信号的编号,就类似于中断编号,而函数指针数组,就类似于我们的中断向量表

block:

这个就是将对应的信号进行屏蔽了,这样,即使收到了该信号,也不会进行递达,除非对这个信号解除屏蔽,这里的block数组和pending数组类似,都是位图结构,

关于屏蔽的理解:屏蔽只是一种状态,和信号有没有产生没有任何关系,只是如果将信号屏蔽了,然后信号产生后就会存在未决,而如果信号没有屏蔽,而信号产生后就会到信号递达

信号忽略与信号阻塞:

这两者是不同的概念的,信号忽略是已经信号递达了,然后对这个信号的处理动作是忽略的

信号阻塞是信号屏蔽,当产生信号的时候对其屏蔽,使其一直处于信号未决状态,没有对其进行处理

注意:

和捕捉信号一样,9号信号和19号信号不能被屏蔽

sigset_t:

上述三张表是OS内核中的数据,所以在用户层是不能够直接对其进行修改的,所以OS就给我们用户层提供了接口,用来对信号进行处理的,当在用户层和内核层进行数据的交互的时候,就需要进行数据的拷贝,所以OS就需要设计输入输出型参数来进行处理,所以就有了位图结构:四个sigset_t 这个数据类型,这个数据类型底层上就是封装了一个unsigned long int 类型的数组,如下

我们是不能够直接对这个类型进行位操作的,需要使用OS提供的系统调用接口来进行操作

#inlcude <signal.h>库文件 

int sigemptyset(sigset_t *set);清空信号集

int sigfillset(sigset_t *set);设置位图,将位图全部置为1

int sigaddset (sigset_t *set, int signo);向指定的信号集中添加特定的信号

int sigdelset(sigset_t *set, int signo);在指定的信号集当中,去掉一个信号

int sigismember(const sigset_t *set, int signo);判断一个信号是否在信号集当中

sigprocmask:

调用sigprocmask可以读取或者更改进程的的信号屏蔽字(阻塞信号集)

形参how有三个选项:

SIG_BLOCK希望添加至当前进程block表中阻塞信号,从set信号集中获取,相当于 mask |= set
SIG_UNBLOCK解除阻塞状态,也是从set信号集中获取,相当于 mask &= (~set)
SIG_SETMASK设置当前进程的block表为set信号集中的block表,相当于mask=set

如果oldset是非空指针,则读取进程的当前信号屏蔽字通过oldset参数传出。如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改

如果oldset和set都是非空指针,则先将原来的信号屏蔽字备份到oldset里,然后根据set和how参数更改信号屏蔽字

如上,返回值:成功返回0,失败返回-1,设置错误码

sigpending:

这个函数就是获取当前进程的信号集,将其从内核中带到用户层

参数:将当前进程的未决信号集带出来

返回值:成功零被返回,失败-1被返回,错误码被设置

应用:

void Printpending(sigset_t pending)
{for(int i = 31; i>=1; i--){if(sigismember(&pending,i)){cout << "1";}else {cout << "0";}}cout << endl;
}int main()
{sigset_t nset,oset;//首先初始化sigemptyset(&nset);sigemptyset(&oset);//然后在将2号信号添加到指定的信号集中sigaddset(&nset,2);//然后设置信号屏蔽字为nset所指向的值sigprocmask(SIG_SETMASK,&nset,&oset);//这个时候就把2号信号屏蔽了sigset_t pending;int cnt = 0;while(true){int n = sigpending(&pending);if(n < 0) continue;//打印信号集Printpending(pending);cnt++;sleep(1);//解除屏蔽if(cnt == 10){sigprocmask(SIG_SETMASK,&oset,nullptr);//解除屏蔽}}return 0;
}

如上,当发送2号信号后,就会是未决状态,当第10秒的时候解除屏蔽2号信号,就会立即执行该信号,就会退出进程

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com