当前位置: 首页 > wzjs >正文

哈尔滨做网站费用报价品牌推广软文200字

哈尔滨做网站费用报价,品牌推广软文200字,著名设计网站deviantart的id模板,南京专业网站建设目录 信号集和信号屏蔽字 信号集 信号屏蔽字 信号位操作函数 sigemptyset sigaddset sigismember sigprocmask sigpending 手动操作让2号信号屏蔽打印pending 信号处理函数sigaction 我们继续来学习信号的捕捉 信号集和信号屏蔽字 信号集 信号集是存储一组信号的…

目录

信号集和信号屏蔽字

信号集

信号屏蔽字

信号位操作函数

sigemptyset

sigaddset

sigismember

sigprocmask

sigpending

手动操作让2号信号屏蔽打印pending

信号处理函数sigaction


我们继续来学习信号的捕捉

信号集和信号屏蔽字

信号集

信号集是存储一组信号的集合,本质也是一个位图,信号集可以存储未决信号,屏蔽信号,所以信号屏蔽字是信号集的一种,我们可以自己创建一个信号集,其类型为sigset_t,sigset_t类型是系统内置类型。

信号屏蔽字

信号屏蔽字Signal Mask进程级 的一个 位掩码,用于指定 哪些信号应该被阻塞(屏蔽),即这些信号在进程解除屏蔽之前不会被递送到进程。每个进程都有一个 信号屏蔽字,它是一个 位图(bitmask),每一位对应一个 信号(如 SIGINTSIGTERM 等):

信号屏蔽字是进程(或线程)的一个状态变量,它决定了当前进程(或线程)正在屏蔽哪些信号。其本质是位图,注意信号屏蔽字就是 Block 表(阻塞信号集),block表的另一种说法是信号屏蔽字。所以说我们创建信号屏蔽字本质不就是创建一个信号集吗。

对进程信号捕捉机制进行操着无非就是操作那三张表,无非就是在改位图的比特位,但是我们不建议直接进行位操作的修改,所以Linux内置了不少的函数帮助我们完成这个事。

信号位操作函数

sigemptyset

sigemptyset 是一个 POSIX 信号处理相关的函数,它用于初始化信号集(sigset_t),并将其清空,即不包含任何信号。

我们如果自己创建一个新的信号集,这时如果只是单纯的sigset_t set,这时信号集set往往是乱码的,不能直接用,我们就需要调用这个函数将其所以的bit位都制成0。

参数是一个指针。返回值如上:

sigaddset

sigaddset 是一个 POSIX 信号处理相关的函数,用于向信号集 (sigset_t) 中添加一个指定的信号。

通过sigaddset添加的信号编号signum,它会修改内部的比特位表示,使得对应信号的比特位变为 1(表示该信号已被添加),是一个由0置1的过程

sigismember

sigismember 是一个 POSIX 信号处理函数,用于检查某个信号是否在指定的 sigset_t 信号集中。

我们值得关注一下这个返回值。

上面这几个是本次试验要用到的函数,我们操作信号主要还是修改进程中的pending表和block表,有没有直接可以对着这两个表进行操作的函数。

sigprocmask

sigprocmask 是 POSIX 提供的信号管理函数,用于修改或查询进程的信号屏蔽字(signal mask),即进程当前阻塞的信号集。被屏蔽的信号不会被进程接收,直到解除屏蔽。

就是操作block表的,具体这么操作取决于此函数的第一个参数how的传参。

how有三种传参方式如上,也就是说可以直接用我们自己创建的信号屏蔽字取代进程中的block。

第二个参数set是输入型参数,第三个参数oldset是输出型参数,用于存放调用前进程的信号屏蔽字。

sigpending

sigpending 用于获取当前进程被阻塞但未被递达的信号(即挂起的信号),就是获取进程的pending表。

这个set参数是输出型参数。

为什么没有修改和替换等的操作,我们每次发信号不就在修改pending表吗,OS接收到信号pending表对应位置不就置1了吗,在 Linux 及 POSIX 规范中,进程的 挂起信号集pending)是内核自动管理的,用户态程序不能直接修改它。这是出于信号处理的设计原则系统安全性的考虑,记得9号信号是不能删除/替代/修改的,如果pending表可以让人随便修改,那不就违背了9号信号的原则了吗?

手动操作让2号信号屏蔽打印pending

我们接着的操作就是运用上面的函数,先屏蔽2号信号,然后获取pending表,只打印其中的32位,接着发送2号信号就可以看到2号信号pending效果,为什么要先屏蔽呢,我们不能让2号信号使得程序终止。

#include<iostream>
#include<unistd.h>
#include<signal.h>
using namespace std;
void PrintPending(const sigset_t& pending)
{cout << "curr pending list [" << getpid() << "]: ";for (int i = 31; i > 0; i--){//判断pending表中是否存在此编号的信号if (sigismember(&pending, i)){cout << 1;}else if (sigismember(&pending, i) == 0){cout << 0;}//忽略对i无效的情况}cout << endl;
}
int main()
{//1.屏蔽2号信号sigset_t block;sigset_t oblock;//初始化sigemptyset(&block);sigemptyset(&oblock);//添加2号信号进block,只是添加还没有设置进内核sigaddset(&block, 2);//设置进内核sigprocmask(SIG_SETMASK, &block, &oblock);while (true){//循环获取并打印内核的pending表sigset_t pending;sigpending(&pending);//打印pending表的前32位(只关注32位信号)PrintPending(pending);sleep(1);}return 0;
}

这里sigprocmask的how可以使用上面的直接替换也可以使用SIG_BLOCK添加。至此我们就完成了先写入2号信号,然后内核屏蔽,打印pending的过程。

可以看到发送2号信号之后pending表果然有记录了(由0变1),为什么没有退出呢,因为block表里面已经事先屏蔽了该信号。

接着我们体验2号信号从屏蔽到接触的过程,接触2号信号只需要再次使用sigprocmask将保存原有block表的oblock替代之前的就可以了。

    //设置进内核sigprocmask(SIG_SETMASK, &block, &oblock);int cnt = 0;while (true){//循环获取并打印内核的pending表sigset_t pending;sigpending(&pending);//打印pending表的前32位(只关注32位信号)PrintPending(pending);sleep(1);cnt++;if (cnt == 15){cout << "解除对2号信号的屏蔽" << endl;//我们这次不关心旧的block表的值sigprocmask(SIG_SETMASK, &oblock, nullptr);}}return 0;
}

我们一旦解除了,2号信号一递达进程就被退出了,所以就停止了!!!

信号处理函数sigaction

sigactionLinux 中用来 处理信号(signal) 的系统调用,它比 signal() 更加强大和可靠。

也就是说sigaction具有和signal相同的功能,就是更改handler特定数组下标里面的内容。

和sigpromask的结构有点像,对一个编号为signum的信号进行act形式的捕捉,返回原有的捕捉方法oldact,这个act和oldact的类型是一个结构体,名字和函数名一样。

我们可以看到,sa_sigaction这个是用来捕捉实时信号的,我们不用管,上面这个就是signal同款的捕捉方式函数,同样的使用函数名传参(回调函数),sa_flag不用管,sa_mask是自定义屏蔽信号的位图,就是想屏蔽更多信号就sigaddset到这里。

sa_mask 里添加的信号会在 信号处理函数运行时自动屏蔽,防止嵌套执行,所以sigaddset添加进入sa_mask的信号就不需要再sigprocmask进内核了,算是一种自动添加到block表的行为

不过:

sigaction 里的 sa_mask 作用是:

当 信号(SIGINT )被触发时(某种行为如Ctrl+C),handler() 运行的这段时间,sa_mask 里的信号会自动被屏蔽,直到 handler() 结束。所以这种屏蔽是暂时的,当信号没有被捕捉或者处理完了不调用handler了就不生效了。

#include<iostream>
#include<signal.h>
#include<unistd.h>
using namespace std;void Printblock()
{sigset_t set;sigset_t olset;sigemptyset(&set);sigemptyset(&olset);sigprocmask(SIG_BLOCK, &set, &olset);for (int i = 31; i >= 0; i--){if (sigismember(&olset, i)){cout << 1;}else{cout << 0;}}cout << endl;
}
void handler(int signo)
{while (1){cout << "get a sig: " << signo << endl;Printblock();sleep(1);}
}int main()
{struct sigaction act, oact;act.sa_handler = handler;sigemptyset(&act.sa_mask);sigaddset(&act.sa_mask, 3);sigaddset(&act.sa_mask, 4);sigaddset(&act.sa_mask, 5);sigaddset(&act.sa_mask, 6);::sigaction(2, &act, &oact);while (true){Printblock();//等待信号到来pause();}
}

可以看到确实如此!!!

当handler方法正在被处理时,此时2号信号的pending表一定是1,但是如果假设handler处理时间很久并且有指令调用系统调用使CPU陷入内核,此时又来了很多个2号信号,OS不允许信号处理方法进行嵌套,当某个信号正在被处理时又来了这个信号,操作系统就不会将pending表其再置1了,转而将block表的对应位置1表示阻塞,等信息处理完自动解除阻塞状态。

pending表由1->0的过程表示信号被处理完了,这个过程是在调用handler表的处理函数之前就置0了。

http://www.dtcms.com/wzjs/288433.html

相关文章:

  • 百度云建设网站seo整站排名
  • 九江网站开发公司台州seo排名优化
  • 坂田做网站多少钱百度助手下载安装
  • 招代理的网站要怎么做的企业营销案例
  • 做中医诊所网站互联网营销案例
  • 网站建设文章网站推广宣传语
  • 手机网站建设官网百度关键词排名爬虫
  • 北京建设官网证书查询廊坊seo优化排名
  • 赤峰市做网站建设的公司如何在百度做推广
  • 网站模板 css口碑营销属于什么营销
  • 网站备案 强制潍坊seo推广
  • 在线登录qq聊天南宁网站优化
  • 有没有专门做联谊的网站小程序商城
  • 网站放到云服务器上怎么做注册一个公司网站需要多少钱
  • 重庆品牌型网站建设西安网络优化大的公司
  • 钢城网站建设百度首页官网
  • web免费代码网站微信营销软件群发
  • 古镇做灯饰网站的公司百度电脑版
  • 同性性做视频网站批量优化网站软件
  • wordpress软件网站模板下载东莞营销型网站建设
  • 郑州做网站的大公司facebook海外推广
  • 建设注册证信息网站刚刚济南发通知
  • 做品牌网站线上营销推广方案
  • wordpress 怎么搬家网络推广和seo
  • 互站网源码搜狗seo软件
  • 上海网站制作优化舆情危机公关公司
  • 网站用什么工具做搜索引擎seo关键词优化方法
  • 网站建设合同图片吸引人的软文
  • 网站如何做信誉认证济南seo排名优化推广
  • 手机网站微信登陆做网络销售感觉自己是骗子