码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-04-22 18:02:49      阅读:192      评论:0      收藏:0      [点我收藏+]

标签:

信号在内核中的表示

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;

}

 

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

标签:

原文地址:http://www.cnblogs.com/shichuan/p/4448051.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!