网站建设如何提案asp企业网站自助建站系统免费版超漂亮版
网站建设如何提案,asp企业网站自助建站系统免费版超漂亮版,成都微网站建设,wordpress 企业主体目录3. 保存信号-内核通过 “未决信号集” 为每个进程存储已产生但未处理的信号3.1 信号处理流程中的不同状态3.2 信号在内核中的表示3.3 sigset_t信号集类型3.4 信号集操作函数3.4.1 sigprocmask读取或更改进程的信号屏蔽字3.4.2 sigpending读取当前进程的未决信号集3.4.3 综合…目录3. 保存信号-内核通过 “未决信号集” 为每个进程存储已产生但未处理的信号3.1 信号处理流程中的不同状态3.2 信号在内核中的表示3.3 sigset_t信号集类型3.4 信号集操作函数3.4.1 sigprocmask读取或更改进程的信号屏蔽字3.4.2 sigpending读取当前进程的未决信号集3.4.3 综合测试用例3. 保存信号-内核通过 “未决信号集” 为每个进程存储已产生但未处理的信号3.1 信号处理流程中的不同状态实际执行信号的处理动作称为信号递达(Delivery)【自定义、默认、忽略】信号从产生到递达之间的状态称为信号未决(Pending)。【信号不是立即处理的信号产生到处理之间的状态成为信号未决】内核通过 “未决信号集Pending Set” 为每个进程存储已产生但未处理的信号进程可以选择阻塞(Block)某个信号。即不让信号未决状态转到递达状态(保持在未决状态)即不处理信号阻塞也称屏蔽被阻塞的信号产生时将保持在未决状态直到进程解除对此信号的阻塞才执行递达的动作。注意阻塞和忽略是不同的只要信号被阻塞就不会递达而信号忽略是递达动作的一种。3.2 信号在内核中的表示信号在内核中的表示示意图进程与信号相关的有三张表[Linux提供信号的操作就是围绕这三张表展开的]pendingunsigned int pending保存收到的信号的位图即未决表。比特位的位置表示的是第几个信号比特位的内容是否收到。blockunsigned int block保存信号的阻塞状态的位图即阻塞表。比特位的位置表示第几个信号比特位的内容是否阻塞。可被递达的信号pending (~block)handlersighandler_t handler[31]函数指针数组下标表示信号编号信号重定义为指定的信号绑定处理动作signal()函数的本质就是修改handler表。SIG_DEF定义即为把0强转成sighandler_t 格式。功能将信号处理恢复默认动作。SIG_IGN定义即为把1强转成sighandler_t格式。功能忽略信号。// 用法signal(信号SIG_DEF)signal(信号SIG_IGN)NAME signal-ANSI C signal handling SYNOPSIS#includesignal.htypedefvoid(*sighandler_t)(int);sighandler_tsignal(intsignum,sighandler_t handler);将下表横着看每一个信号一行。每个信号都有两个标志位分别表示阻塞(block)和未决(pending)还有一个函数指针表示处理动作。信号产生时内核在进程控制块中设置该信号的未决标志直到信号递达才清除该标志。在上图的例子中SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。SIGINT信号产生过但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略但在没有解除阻塞之前不能忽略这个信号因为进程仍有机会改变处理动作之后再解除阻塞。SIGQUIT信号未产生过,一旦产生SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler。如果在进程解除对某信号的阻塞之前这种信号产生过多次将如何处理? POSIX.1允许系统递送该信号一次或多次。Linux是这样实现的: 常规信号在递达之前产生多次只计一次而实时信号在递达之前产生多次可以依次放在一个队列里。本章不讨论实时信号。// 内核结构 2.6.18structtask_struct{.../* signal handlers */structsighand_struct*sighand;sigset_t blockedstructsigpendingpending;...}structsighand_struct{atomic_t count;structk_sigactionaction[_NSIG];// #define _NSIG 64spinlock_t siglock;};struct__new_sigaction{__sighandler_t sa_handler;unsignedlongsa_flags;void(*sa_restorer)(void);/* Not used by Linux/SPARC */__new_sigset_t sa_mask;};structk_sigaction{struct__new_sigactionsa;void__user*ka_restorer;};/* Type of a signal handler. */typedefvoid(*__sighandler_t)(int);structsigpending{structlist_headlist;sigset_t signal;};3.3 sigset_t信号集类型从上图来看每个信号只有一个bit的未决标志非0即1不记录该信号产生了多少次阻塞标志也是这样表示的。因此未决和阻塞标志可以用相同的数据类型sigset_t来存储sigset_t称为信号集这个类型可以表示每个信号的“有效”或“无效”状态在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。下一节将详细介绍信号集的各种操作。阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask)这里的“屏蔽”应该理解为阻塞而不是忽略。信号屏蔽字(Signal Mask)类似权限的umask3.4 信号集操作函数sigset_t类型对于每种信号用一个bit表示“有效”或“无效”状态, 至于这个类型内部如何存储这些bit则依赖于系统实现, 从使用者的角度是不必关心的, 使用者只能调用以下函数来操作sigset_ t变量,而不应该对它的内部数据做任何解释, 比如用printf直接打印sigset_t变量是没有意义的。#includesignal.hintsigemptyset(sigset_t*set);// 初始化信号集为空集: 将参数 set 指向的 sigset_t 变量清空。intsigfillset(sigset_t*set);// 初始化信号集为全集: 将参数 set 指向的 sigset_t 变量填充为包含所有可被捕获、阻塞的信号逻辑上包含所有有效信号。intsigaddset(sigset_t*set,intsigno);// 向已初始化的信号集中添加指定信号将信号编号 signo 对应的信号加入到 set 指向的信号集中。intsigdelset(sigset_t*set,intsigno);// 从已初始化的信号集中删除指定信号将信号编号 signo 对应的信号从 set 指向的信号集中移除。intsigismember(constsigset_t*set,intsigno);//判断指定信号是否为信号集的成员检查信号编号 signo 对应的信号是否存在于 set 指向的信号集中。函数sigemptyset初始化set所指向的信号集使其中所有信号的对应bit清零表示该信号集不包含任何有效信号。函数sigfillset初始化set所指向的信号集使其中所有信号的对应bit置位表示该信号集的有效信号包括系统支持的所有信号。注意,在使用sigset_ t类型的变量之前一定要调 用sigemptyset或sigfillset做初始化使信号集处于确定的 状态。初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信号。这四个函数都是成功返回0出错返回-1。sigismember是一个布尔函数用于判断一个信号集的有效信号中是否包含 某种 信号,若包含则返回1不包含则返回0,出错返回-1。3.4.1 sigprocmask读取或更改进程的信号屏蔽字调用函数sigprocmask 可以读取或更改进程的信号屏蔽字(阻塞信号集)。代码块#includesignal.hintsigprocmask(inthow,constsigset_t*set,sigset_t*oset);返回值:若成功则为0,若出错则为-1如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则 更改进程的信 号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号 屏蔽字备份到oset里,然后 根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表说明了how参数的可选值。如果调用sigprocmask解除了对当前若干个未决信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达。3.4.2 sigpending读取当前进程的未决信号集#includesignal.hintsigpending(sigset_t*set);读取当前进程的未决信号集,通过set参数传出。 调用成功则返回0,出错则返回-13.4.3 综合测试用例综合测试用例1屏蔽信号再发送信号观察未决表pending#includeiostream#includecstdio#includevector#includefunctional#includeunistd.h#includesignal.h#includesys/types.hvoidPrintPending(sigset_tpending){printf(我是一个进程(%d),pending: ,getpid());for(intsigno31;signo1;signo--){if(sigismember(pending,signo))std::cout1;elsestd::cout0;}std::coutstd::endl;}intmain(){// 1.屏蔽2号信号sigset_t block,oblock;sigemptyset(block);sigemptyset(oblock);sigaddset(block,SIGINT);// for(int i 1; i 31; i) // 5.将所有信号屏蔽并用kill 信号 pid测试// sigaddset(block, i);intnsigprocmask(SIG_SETMASK,block,oblock);(void)n;// 4.重复获取打印过程while(true){// 2.获取pending信号集合sigset_t pending;intmsigpending(pending);// 3.打印PrintPending(pending);sleep(1);}return0;}结论9号信号不可被捕捉不可被阻塞综合测试用例2测试功能在代码结尾注释#includeiostream#includecstdio#includevector#includefunctional#includeunistd.h#includesignal.h#includesys/types.hvoidPrintPending(sigset_tpending){printf(我是一个进程(%d),pending: ,getpid());for(intsigno31;signo1;signo--){if(sigismember(pending,signo))std::cout1;elsestd::cout0;}std::coutstd::endl;}voidhandler(intsig){std::cout######################std::endl;std::cout递达sig信号std::endl;sigset_t pending;intmsigpending(pending);PrintPending(pending);// 如果是 0000 0010 则结论为处理完handler函数再将2号信号置0。// 验证结果0000 0000 实际结论为先给pending未决表的2号信号置0再执行handler函数。std::cout######################std::endl;}intmain(){// 补0.对2号信号的功能重定义signal(SIGINT,handler);// 1.屏蔽2号信号sigset_t block,oblock;sigemptyset(block);sigemptyset(oblock);sigaddset(block,SIGINT);// for(int i 1; i 31; i) // 5.将所有信号屏蔽并用kill 信号 pid测试// sigaddset(block, i);intnsigprocmask(SIG_SETMASK,block,oblock);(void)n;// 4.重复获取打印过程intcnt0;while(true){// 2.获取pending信号集合sigset_t pending;intmsigpending(pending);// 3.打印PrintPending(pending);if(cnt10){// 5.恢复对2号信号的block情况std::cout解除对2号信号的屏蔽std::endl;sigprocmask(SIG_SETMASK,oblock,nullptr);}sleep(1);cnt;}return0;}// 前提执行过程中使用Print函数每秒打印pending未决表// 1.将2号信号重定义// 2.将2号信号屏蔽// 3.运行程序给进程发送2号信号// 4.10秒之后对2号信号恢复即接触屏蔽// 5.解除之后调用重定义后的2号信号函数// 5.1 验证先给未决表置0还是先执行2号信号函数(handler函数中)结论在递达之前先清空pending未决表中对应的信号位图1 → 0