[学习笔记]信号的阻塞和未达


信号在内核中的表示

q  执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending)。进程可以选择阻塞(Block)某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。

q  注意,阻塞和忽略是不同,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。信号在内核中的表示可以看作是这样的:


说明1)PCB进程控制块中结构体中有信号屏蔽状态字(block),信号未决状态字(pending)还有是否忽略标志;

说明2)信号屏蔽状态字(block),1代表阻塞、0代表不阻塞;信号未决状态字(pending)的1代表未决(表示有未达信号),0代表信号可以抵达了;

说明3)向进程发送SIGINT,内核首先判断信号屏蔽状态字是否阻塞,信号未决状态字(pending相应位制成1;若阻塞解除,信号未决状态字(pending)相应位制成0;表示信号可以抵达了。

说明4)block状态字、pending状态字 64bit;//socket select

说明5)block状态字用户可以读写,pending状态字用户只能读;这是信号设计机制。

思考1:状态字都64bit,编程时,如何表示状态字那?

思考2:block状态字信息如何获取或者操作那?哪些api?

思考3:pending状态字信息如何获取或者操作那?哪些api?


信号集操作函数(状态字表示)

q  #include <signal.h>

q  int sigemptyset(sigset_t *set); 把信号集清空 64bit/8=8个字节

q  int sigfillset(sigset_t *set); 把信号集置成1

q  int sigaddset(sigset_t *set, int signo); 根据signo,把信号集中的对应bit置成1

q  int sigdelset(sigset_t *set, int signo); 根据signo,把信号集中的对应bit置成0

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


sigprocmask读取或更改进程的信号屏蔽状态字(block)

q  #include <signal.h>

q  int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

q  功能:读取或更改进程的信号屏蔽字。

q  返回值:若成功则为0,若出错则为-1

q  如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表说明了how参数的可选值。

how含义

说明:SIG_BLOCK ,讲信号集set添加到进程block状态字中。


sigpending获取信号未决状态字(pending)信息

NAME

sigpending - examine pending signals

SYNOPSIS

#include <signal.h>

int sigpending(sigset_t *set);

DESCRIPTION

sigpending()  returns the set of signals that are pending for delivery to the calling thread (i.e., the signals which have been raised while blocked).  The mask of pending signals is returned in set.

信号阻塞未达编程实践


综合实验,

SIGINT信号未设置阻塞,查看未决关键字

SIGINT信号设置阻塞,查看未决关键字

SIGINT信号解除阻塞,查看未决关键字(通过ctrl+\ SIGQUIT 解除阻塞)

//演示信号从产生到抵达的整个过程

//信号的阻塞和解除阻塞综合实验

//设置信号阻塞和非阻塞,设置ctl+q来解除信号阻塞

void handler(int sig)

{

if (sig == SIGINT)

printf("recv a sig=%d\n", sig);

else if (sig == SIGQUIT)

{

sigset_t uset;

sigemptyset(&uset);

sigaddset(&uset, SIGINT);

//ctr + \ 用来接触  SIGINT 信号

//解除阻塞

sigprocmask(SIG_UNBLOCK, &uset, NULL);

}

}

void printsigset(sigset_t *set)

{

int i;

for (i=1; i<NSIG; ++i)

{

if (sigismember(set, i))

putchar(‘1‘);

else

putchar(‘0‘);

}

printf("\n");

}

//3 连续的按ctrl+c键盘,虽然发送了多个SIGINT信号,但是因为信号是不稳定的,只保留了一个。

//不支持排队

int main(int argc, char *argv[])

{

sigset_t pset; //用来打印的信号集

sigset_t bset; //用来设置阻塞的信号集

sigemptyset(&bset);

sigaddset(&bset, SIGINT);

if (signal(SIGINT, handler) == SIG_ERR)

ERR_EXIT("signal error");

if (signal(SIGQUIT, handler) == SIG_ERR)

ERR_EXIT("signal error");

//读取或更改进程的信号屏蔽字 这里用来阻塞ctrl+c信号

//ctrl+c信号被设置成阻塞,即使用户按下ctl+c键盘,也不会抵达

sigprocmask(SIG_BLOCK, &bset, NULL);

for (;;)

{

//获取未决 字信息

sigpending(&pset);

//打印信号未决  sigset_t字

printsigset(&pset);

sleep(1);

}

return 0;

}

复制去Google翻译翻译结果

时间: 2024-08-26 15:01:20

[学习笔记]信号的阻塞和未达的相关文章

Linux信号阻塞与未达

信号在内核中的表示 执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending).进程可以选择阻塞(Block)某个信号.被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作. 注意,阻塞和忽略是不同,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作.信号在内核中的表示可以看作是这样的: @font-face { font-family: "Times New Roman"; }@font-fa

PHP stream 学习笔记一(同步阻塞 IO 模型)

原文http://blog.csdn.net/shagoo/article/details/6396089 [[email protected] php]# vi server_one.php <?php set_time_limit(0); class SocketServer { private static $socket; public function __construct($port) { global $errno, $errstr; if ($port < 1024) { d

[学习笔记]信号的高级用法

sigaction函数注册信号处理函数 sigaction函数 q  包含头文件<signal.h> q  功能:sigaction函数用于改变进程接收到特定信号后的行为. q  原型: int  sigaction(int signum,const struct sigaction *act,const struct sigaction *old); q  参数 q  该函数的第一个参数为信号的值,可以为除SIGKILL及SIGSTOP外的任何一 个特定有效的信号(为这两个信号定义自己的处理

【Python学习笔记】-APP图标显示未读消息数目

以小米手机系统为例,当安装的某个APP有未读消息时,就会在该APP图标的右上角显示未读消息的数目.本文主要解说怎样用Python语言实现图标显示未读消息的数目.首先,还是要用到Python中PIL库,关于Linux下怎样安装PIL库,请大家參考这篇博客:http://blog.csdn.net/kevin_zhai/article/details/47720721,里面有具体的安装过程.实现的原理非常easy,直接用Image读取原始图标.然后将未读消息的数目插入到图标的右上角就可以. 脚本代码

[学习笔记]信号基本概念(中断和信号)/名称及常用信号/信号处理/signal函数实践

1基本概念 中断 q  中断是系统对于异步事件的响应 q  中断信号 q  中断源 q  现场信息 q  中断处理程序 q  中断向量表 异步事件的响应:进程执行代码的过程中可以随时被打断,然后去执行异常处理程序 生活中的中断和计算机系统中的中断 1)  无中断生活场景 张三看书,厨房烧水 2)有中断的生活场景 张三看书,设置闹钟,厨房烧水. 闹钟发出中断信号,张三把书合好(第20页),去厨房把开水事情处理好,张三重新打开20页进行阅读. 3)计算机系统的中断场景 中断源发出中断信号,CPU判断

[学习笔记]信号发送

kill函数 Kill基本用法 发送信号的函数有kill和raise 区别:kill既可以向自身发送信号,也可以向其他进程发送信号: raise函数向进程自身发送信号. Int kill(pid_t pid, int siq) int raise(int signo) Int kill(pid_t pid, int siq) 参数组合情况解释: kill(pid_t pid, int siq) pid>0 将信号sig发给pid进程 pid=0 将信号sig发给同组进程 pid=-1 将信号si

(原创)c#学习笔记03--变量和表达式04--表达式02--赋值运算符

3.4.2  赋值运算符 表3-9列出了这些运算符及其说明. 可以看出,这些运算符把var1也包括在计算过程中,下面的代码: var1 += var2; 与下面的代码结果相同. var1 = var1 + var2; note: +=运算符也可以用于字符串,与+运算符一样. 使用这些运算符,特别是在使用长变量名时,可以使代码更便于阅读.

(原创)c#学习笔记03--变量和表达式04--表达式01--数学运算符

3.4  表达式 把变量和字面值(在使用运算符时,它们都称为操作数)与运算符组合起来,就可以创建表达式,它是计算的基本构件. 本章主要介绍数学和赋值运算符,而逻辑运算符将在第4章中介绍,主要论述控制程序流程的布尔逻辑. 运算符大致分为如下3类. 一元运算符,处理一个操作数: 二元运算符,处理两个操作数: 三元运算符,处理三个操作数: 大多数运算符都是二元运算符,只有几个一元运算符和一个三元运算符,即条件运算符(条件运算符是一个逻辑运算符,详见第4章).下面先介绍数学运算符,它包括一元运算符和二元

APUE学习笔记——10.9 信号发送函数kill、 raise、alarm、pause

转载注明出处:Windeal学习笔记 kil和raise kill()用来向进程或进程组发送信号 raise()用来向自身进程发送信号. #include <signal.h> int kill(pid_t pid,int signo); int raise(int signo); Both return: 0 if OK,?1 on error kill向进程号为pid的进程发送signo信号 能够看出 以下两行代码是等价的: kill(getpid(), signo); raise(sig