zoukankan      html  css  js  c++  java
  • 信号之信号集操作

    1、信号在内核中的表示
      执行信号的处理动作称为信号递达。信号从产生到递达状态之间的状态成为未决(pending)。
    进程可以选择阻塞某个信号。被阻塞的信号产生时将保持在未决状态。直到进程解除对此信号的阻塞,才可以执行递达动作。
      如下图,进程任务结构(PCB)中包含:信号屏蔽字64位,linux中用sigset_t类型表示(block 1,信号掩码); 

    未决状态字(pending 1)...阻塞信号的话,到达就会处于未决。

      如图,SIGINT信号,发送给进程,进程信号屏蔽字屏蔽信号,那么其被阻塞,也处于未决状态。当将信号屏蔽改为0,信号就会递达,进而执行信号处理函数。

    信号集操作函数,下面这5个函数只是会改变信号集中的信号屏蔽字,但是并不会改变进程的信号屏蔽字。

    1、int sigemptyset(sigset_t *set);//清空

    2、int sigfillset(sigset_t *set);//置1

    3、int sigaddset(sigset_t *set,int signo);

    4、int sigdelset(sigset_t *set,int signo);

    5、int sigismember(const sigset_t *set,int signo);

    sigprocmask函数可以获取或者改变进程中的信号屏蔽字。

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

      功能:读取或者更改进程的信号屏蔽字。成功返回0,出错返回-1.

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

    那么how参数含义:

    SIG_BLOCK:set包含了我们希望添加到当前信号屏蔽字的信号,相当于mask=mask|set;

    SIG_UNBLOCK:set包含了我们希望从当前信号屏蔽字中解除阻塞的信号,相当于mask=mask&~set;

    SIG_SETMASK:设置当前信号屏蔽字为set所指向的值,相当于mask=set.

    下面的例子说明信号从产生到递达的过程:

     1 #include<unistd.h>
     2 #include<sys/types.h>
     3 #include<sys/stat.h>
     4 #include<fcntl.h>
     5 #include<stdlib.h>
     6 #include<stdio.h>
     7 #include<errno.h>
     8 #include<string.h>
     9 
    10 #include<signal.h>
    11 #define ERR_EXIT(m)
    12     do
    13     {
    14         perror(m);
    15         exit(EXIT_FAILURE);
    16     }while(0)  //宏要求一条语句
    17 void handler(int sig);
    18 void printsigset(sigset_t *set)
    19 {
    20     int i;//NSIG表示信号最大值,64
    21     for(i=1;i<NSIG;i++){
    22         if(sigismember(set,i))
    23             putchar('1');
    24         else putchar('0');
    25     }
    26     printf("
    ");
    27 }
    28 int main(int argc,char*argv[])
    29 {
    30     sigset_t pset;
    31     sigset_t bset;
    32     sigemptyset(&bset);//sigset_t 用之前必须置0或置1
    33     if(signal(SIGINT,handler)==SIG_ERR)
    34         ERR_EXIT("signal error");
    35 //    if(signal(SIGQUIT,handler)==SIG_ERR)
    36 //        ERR_EXIT("signal error");//再安装一个信号,按下ctrl+解除SIGINT阻塞,信号递达(信号处理函数)
    37     sigaddset(&bset,SIGINT);//SIGINT加入信号集。
    38     sigprocmask(SIG_BLOCK,&bset,NULL);//对bset操作,改变信号屏蔽字,阻塞SIGIN信号。按下ctrl+c也会被阻塞。这个是不可靠信号,只会阻塞一个信号,不会排队。
    39     for(;;)
    40     {
    41         sigpending(&pset);//获取未决信号,没有阻塞则没有未决
           /*
            sigpending函数返回信号集,其中的各个信号对于调用进程是阻塞的而不能递送,因而也一定是当前未决的。该信号集通过set参数返回。(这些信号是已经产生的信号,
    但因为信号屏蔽字中对其设置了屏蔽位,从而被阻塞,不能递送给进程的那些信号。注意sigpending返回的信号集与信号屏蔽字的区别。从集合角度来讲,此信号集是当前信号屏蔽字的子集。)
            */
    42 sleep(1); 43 printsigset(&pset); 44 sleep(1); 45 } 46 sleep(1); 47 return 0; 48 } 49 50 void handler(int sig)//sig是signum 51 { 52 if(sig==SIGINT) 53 printf("receive a sig %d ",sig); 54 /* else if(sig==SIGQUIT) 55 { 56 sigset_t uset; 57 sigemptyset(&uset); 58 sigaddset(&uset,SIGINT); 59 sigprocmask(SIG_UNBLOCK,&uset,NULL);//解除uset中信号的阻塞 60 } 61 */ 62 }
  • 相关阅读:
    MyBatis学习总结(5)——实现关联表查询
    MyBatis学习总结4--解决字段名与实体类属性名不相同的冲突
    MyBatis学习总结3-优化MyBatis配置文件
    各种数据库的数据类型
    Ubuntu下jdk配置
    null和""的区别
    单例模式
    知识体系(不断更新)
    Servlet错误一览
    如何锻炼敲代码的能力
  • 原文地址:https://www.cnblogs.com/wsw-seu/p/8367009.html
Copyright © 2011-2022 走看看