您的位置:首页 > 教育 > 培训 > 竞价推广公司_泰安招聘信息最新招聘2022_站长工具是什么意思_百度seo还有前景吗

竞价推广公司_泰安招聘信息最新招聘2022_站长工具是什么意思_百度seo还有前景吗

2024/10/6 6:49:56 来源:https://blog.csdn.net/taduanlangan/article/details/142605967  浏览:    关键词:竞价推广公司_泰安招聘信息最新招聘2022_站长工具是什么意思_百度seo还有前景吗
竞价推广公司_泰安招聘信息最新招聘2022_站长工具是什么意思_百度seo还有前景吗
1. 信号处理机制的 “三张表”

kill -l :前 31 个信号为系统标准信号。

block pending handler 三张表保存在每个进程的进程控制块 —— pcb 中,它们分别对应了某一信号的阻塞状态、待处理状态以及处理方式。

  • block :通过 sigset_t 类型实现,是一个位字段集合,每一位对应一个信号;如果某一位被设置,则对应的信号会被阻塞;信号的阻塞状态 与 该信号是否被发送到进程 无关

  • pending :与 block 相同,通过 sigset_t 类型实现,用于记录 已经发送给进程但未被处理 的信号。

  • handler :函数指针数组,指向各个信号的处理方法(函数)。

2. 介绍几个信号处理的系统调用
  • sigemptyset :用于初始化一个信号集为空,即将信号集中的所有信号位都清零。

    创建一个 sigset_t 类型的变量,在对该变量进行各种信号处理操作之前,先要使用 sigemptyset 对该变量初始化。

	sigset_t sig;sigemptyset(&sig); // 对 sig 初始化, success -> 0, fail -> -1
  • sigaddset :用于在一个已存在的信号集中添加信号。
	sigaddset(&sig, SIGINT); // success return 0, fail return -1
  • sigprocmask :用于更改当前进程的信号掩码,简单来说即设置哪些信号被阻塞。
 sigprocmask(int how, const sigset_t* signal, sigset_t* old_signal);

how 的处理方式, SIG_BLOCK SIG_UNBLOCK SIG_SETMASK

SIG_BLOCK : 设置新的信号掩码,同时保留旧的信号掩码

SIG_UNBLOCK : 取笑新信号掩码中的信号阻塞,并保留旧的信号掩码

SIG_SETMASK : 设置新的信号掩码,并丢弃旧的信号掩码

	sigset_t oldsig;sigemptyset(&oldsig);sigprocmask(SIG_SETMASK, &sig, &oldsig);
  • sigpending :用于获取当前进程中待处理的信号集。
	sigset_t pending;sigemptyset(&pending);sigpending(&pending);
  • sigismember :用于测试一个信号是否在一个信号集中,存在返回 1,否则返回 0。
	sigismember(&pending, SIGINT);
3. demo —— 示范案例

demo 中主要完成以下四个动作:

  1. 屏蔽 2 号信号 —— SIGINT
  2. 获取当前进程的 pending
  3. 打印 pending 表
  4. 取消对 2 号信号的屏蔽

其中,2.3. 是 “同时” 且 重复 进行的,意味着将出现这样一个现象:当前进程在接收 2 号信号之前,pending 表 2 号信号对应位置为 0;向当前进程发生 2 号信号后,pending 表 2 号信号位置被设置。

以及,取消对 SIGINT 的屏蔽后,2 号信号会被立即递达,进程结束。

1) 屏蔽 2 号信号
#include <iostream>
using namespace std;
#include <signal.h>int main()
{// 1. 屏蔽 2 号信号sigset_t block;sigset_t old_block;sigemptyset(&block);sigemptyset(&old_block);sigaddset(&block, SIGINT);sigprocmask(SIG_SETMASK, &block, &old_block);cout << "process pid: " << getpid() << endl;cout << "block SIGINT success ..." << endl;return 0;
}
2) 获取当前进程的 pending 表 | 3) 打印 pending 表
#include <unistd.h>void PrintSig(sigset_t pending)
{cout << "process pending: ";for (int i = 31; i >= 1; i--){if (sigismember(&pending, i))cout << "1";else cout << "0";}cout << endl;
}int main()
{// ...while (1){// 2. 获取当前 pending 表sigset_t pending;sigemptyset(&pending);sigpending(&pending);// 3. 打印 pending 表PrintSig(pending);sleep(1);}}

将这部分代码先运行起来,并对该进程发送一个 SIGINT 信号,观察现象:
在这里插入图片描述

当前进程(3988092)pending 表的 2 号信号对应位置被设置,但进程没有退出!

4) 取消对 2 号信号的屏蔽
int main()
{while (1) {// ...   // 4. 取消对 2 号信号对屏蔽++cnt;if (cnt == 20){sigprocmask(SIG_UNBLOCK, &block, &old_block);}}
}

为了使 2 号信号恢复且被递达后的观察效果更明显,我们对 PrintSig 函数 做一下优化,再 对 2 号信号的处理程序自定义

介绍一个新的系统调用接口:signal

signal() 允许我们为特定信号指定一个处理函数 —— handler() 是一个参数类型为 int 返回值为 的函数, 当信号到达时,该函数将被调用。

#include <iostream>
using namespace std;
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>void PrintSig(sigset_t pending, int count)
{cout << "process pending: ";for (int i = 31; i >= 1; i--){if (sigismember(&pending, i))cout << "1";elsecout << "0";}cout << " , cnt: " << count << endl;
}void handler(int signal)
{cout << "2 号信号被递达" << endl;exit(1);
}int main()
{signal(SIGINT, handler); // 对 SIGINT 的处理方式重定义// 1. 屏蔽 2 号信号sigset_t block;sigset_t old_block;sigemptyset(&block);sigemptyset(&old_block);sigaddset(&block, SIGINT);sigprocmask(SIG_SETMASK, &block, &old_block);cout << "process pid: " << getpid() << endl;cout << "block SIGINT success ..." << endl;int cnt = 0;while (1){// 2. 获取当前 pending 表sigset_t pending;sigemptyset(&pending);sigpending(&pending);// 3. 打印 pending 表 PrintSig(pending, cnt);sleep(1);// 4. 取消对 2 号信号对屏蔽++cnt;if (cnt == 20){sigprocmask(SIG_UNBLOCK, &block, &old_block);}}return 0;
}

在这里插入图片描述

进程运行 20 秒后,SIGINT 的屏蔽被取消,SIGINT 被递达,进程终止!

4. 对 SIGKILL 和 SIGSTOP 的验证

pid 为 “当前进程” 的 pid

while :; do for i in {1..8}; do kill -$i pid; done; sleep 1; done    # 对进程发送 1~8 号信号
while :; do for i in {10..18}; do kill -$i pid; done; sleep 1; done  # 对进程发送 10~18 号信号
while :; do for i in {20..31}; do kill -$i pid; done; sleep 1; done  # 对进程发送 20~31 号信号

对原代码做出修改:使用 for 循环,让进程阻塞 1~31 号信号

随后,在另一窗口使用 bash 脚本,分别向当前进程发送 1~8 、 10~18 、 20~31 号信号,观察进程的 pending 表;

在过程中,对当前进程发送 9 号信号 和 19 号信号,观察现象。

#include <iostream>
using namespace std;
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>void PrintSig(sigset_t pending)
{cout << "process pending: ";for (int i = 31; i >= 1; i--){if (sigismember(&pending, i))cout << "1";elsecout << "0";}cout << endl;
}void handler(int signal)
{cout << "2 号信号被递达" << endl;exit(1);
}int main()
{// 1. 屏蔽 1~31 号信号sigset_t block;sigset_t old_block;sigemptyset(&block);sigemptyset(&old_block);for (int i = 1; i <= 31; i++){sigaddset(&block, i);}sigprocmask(SIG_SETMASK, &block, &old_block);cout << "process pid: " << getpid() << endl;cout << "block signal success ..." << endl;int cnt = 0;while (1){// 2. 获取当前 pending 表sigset_t pending;sigemptyset(&pending);sigpending(&pending);// 3. 打印 pending 表PrintSig(pending);sleep(2);}return 0;
}
  • 对当前进程发送 1~8 号信号 和 9 号信号

在这里插入图片描述

对当前进程发送 1~8 号信号,进程没有结束。

对当前进程发送 9 号信号,进程终止!

  • 对当前进程发送 10~18 号信号 和 19 号信号

在这里插入图片描述

对当前进程发送 10~18 号信号,进程没有结束。

对当前进程发送 19 号信号,进程终止!

  • 对当前进程发送 20~31 号信号

在这里插入图片描述

对当前进程发送 20~31 号信号,进程没有结束。

总结:9 号信号 — SIGKILL 及 19 号信号 — SIGSTOP 是特殊信号,不能被阻塞,因为它们具有重要作用!

版权声明:

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

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