# 信号量相关函数解析

信号量一般用于进程之间通信,在c++关于信号量及其相关函数的定义均声明在signal.h中(linux系统)。信号集是信号量的集合,可以使用sigset_t进行定义,我们一般需要关注的信号集为阻塞集与未决集,阻塞集指明将哪些信号阻塞,集合中对应位置1,表示阻塞该信号。未决集指明哪些信号还未处理,对应位为1,指该信号还未从处理。

sigaction()函数

该函数的作用对象为单个信号,功能是对信号作出相应的处理动作,函数原型为

int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

  • 第一个参数是要捕获的信号,比如SIGCHLD就是子进程死亡之后发出的信号,填入之后,父进程就会监视并捕获该信号以作出相应的动作。
  • 第二个参数是一个结构体(下文会详细解释该结构体),其主要的作用就是指明捕获到信号之后要执行的动作。
  • 第三个参数是保存与该信号之前的动作,如果不保存可以直接置空。

sigaction的结构体声明如下:

       struct sigaction {
           void     (*sa_handler)(int);
           void     (*sa_sigaction)(int, siginfo_t *, void*);
           sigset_t   sa_mask;
           int        sa_flags;
           void     (*sa_restorer)(void);
       };

对于上述的结构体我们只关注三个属性:

  • void (*sa_handler)(int):该函数指针指向与信号绑定的动作函数,即只要信号被捕获,就执行该函数指针指向的函数。
  • sigset_t sa_mask:设置阻塞集,表示执行信号动作时需要阻塞哪些信号,在c++里默认新到来的信号会阻塞之前的信号,也就是说如果进程正在执行信号A的处理函数,此时又捕获到一个信号B,B会将A阻塞,进程会暂停A的处理函数转而执行B的处理函数,之后再回到断口处,继续执行A的处理函数。如果希望在处理A的处理函数时不被打断,就需要设置阻塞集,表示阻塞那些函数,如果不需要阻塞,可以使用sigemptyset()将阻塞集置空就好。
  • int sa_flags:特殊标志,一般置0,如果置1,会选择另一种结构体,不予考虑。

信号集相关函数

上节描述了如何使用sigaction捕获信号并触发相应的动作,但是在一个进程中往往不止有一个信号,这就涉及信号的阻塞和排队问题,默认情况下,新捕获的信号会打断旧信号的处理函数的执行,当然,signal.h头文件中定义了一系列关于信号集的操作,来帮助我们顺畅的管理信号集。

int sigemptyset(sigset_t *set)

该函数将传入的信号集所有位初始化为0,一般用于信号集的初始化,不做修改将不阻塞而任何信号。

int sigfillset(sigset_t *set)

该函数将传入的信号集所有初始化为1,一般用于初始化,不做修改将阻塞所有信号。

int sigaddset(sigset_t *set, int signum)

该函数将指定信号加入信号集,参数一为传入的信号集,参数二signum为指定的要加入到set中的信号。

int sigdelset(sigset_t *set, int signum)

该函数将指定信号从信号集中删除,即将信号signum从信号集set中删除

int sigismember(const sigset_t *set, int signum)

该函数判断传入的信号集中上是否包含某特定信号,即判断信号集set中是否包含信号signum

sigprocmask

上一小节中介绍了信号集与其基本的操作(包括初始化、插入、删除等),我们创建信号集的目的是为了帮助流畅的捕获信号,所以我们需要把创建好的信号集作为一种配置来控制信号的捕获顺序,以免信号的默认中断机制打断我们对某一信号的持续捕获。signal.h允许我们使用sigprocmask函数将自定义信号集作为阻塞的配置。该函数原型为:

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)

参数解析

  • int how:该参数表示操作类型,即要对传入的信号集做什么操作,是将信号集加入阻塞,还是为该信号集中的信号清除阻塞状态,该参数有三个值可选:SIG_BLOCK--表示求set与原生的信号集的并集作为阻塞集,即将set中的信号加入阻塞;SIG_UNBLOCK--表示求原生信号集与set的差集作为阻塞集使用,即将set中的信号清除阻塞状态。SIG_SETMASK--将set信号集将原生的阻塞信号集覆盖,直接作为阻塞集使用(用的很少)。
  • const sigset_t *set:传入的自定义的信号集
  • sigset_t *oldset:该参数保存原生的信号阻塞集,不保存可以置空

代码演示

#include <unistd.h>
#include <iostream>
#include <signal.h>
#include <wait.h>

void alprint(int num){         //信号处理函数
    for(int i=0;i<num;++i){
        sleep(1);
        std::cout<<num<<"  "<<i<<std::endl;
    }
}


int main(){
    sigset_t set;//创建信号集
    sigemptyset(&set);//将信号集初始化为空
    sigaddset(&set,SIGINT);//将键盘中断信号(ctrl-c)加入信号集
    sigprocmask(SIG_BLOCK,&set,NULL);//加入阻塞集
     
    struct sigaction act;  //定义信号处理结构体
    act.sa_handler = alprint; //绑定信号处理函数
    sigemptyset(&act.sa_mask); //清空阻塞集
    act.sa_flags = 0;  
    int num;                  //要传入的信号
    std::cin>>num;
    sigaction(num,&act,NULL); //捕获信号,并执行处理程序
    raise(num);                //发出信号
    return 0;
    
}


在上述程序中,我们将键盘中断信号(ctrl-c)加入阻塞集,然后对我们键入的数字num进行捕捉并打印numnum的值,并且打印期间不会被ctrl-c打断。实验步骤:运行上面的程序(linux下),输入一个数字(稍微大点,好观察)然后回车,发现终端在打印刚刚输入的数字,此时按下ctrl-c,发现无法打断程序的执行,实验结束(可以按ctrl-z来结束程序)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354