二 Linux进程间通信( 四 )


下面是信号集操作函数的原型:
#include <signal.h>int sigemptyset(sigset_t *set);int sigfillset(sigset_t *set);int sigaddset(sigset_t *set, int signum);int sigdelset(sigset_t *set, int signum);int sigismember(const sigset_t *set, int signum);

  • sigemptyset: 初始化set指向的信号集,将所有比特位置0
  • sigfillset: 初始化set指向的信号集,将所有比特位置1
  • sigaddset: 把set指向的信号集中signum信号对应的比特位置1
  • sigdelset: 把set指向的信号集中signum信号对应的比特位置0
  • sigismember: 判断signum信号是否存在set指向的信号集中(本质是信号判断对应位是否为1)
注意: 在实现这些函数之前,需要使用sigemptyset 或sigfillset对信号集进行初始化 。前四个函数的返回值是成功返回0 , 失败返回-1 。最后一个函数的返回值是真返回1,假返回-1
阻塞信号集操作函数——sigprocmask:
#include<signal.h>int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);功能:检查或修改信号阻塞集 , 根据how指定的方法对进程的阻塞集合进行修改,新的信号阻塞集由set指定,而原先的信号阻塞集合由oldset保存 。参数:how:信号阻塞集合的修改方法,有3种情况:SIG_BLOCK:向信号阻塞集合中添加set信号集 , 新的信号掩码是set和旧信号掩码的并集 。相当于mask=mask丨set 。SIG_UNBLOCK:从信号阻塞集合中删除set信号集,从当前信号掩码中去除set中的信号 。相当于mask=mask&~set 。SIG_SETMASK:将信号阻塞集合设为set信号集,相当于原来信号阻塞集的内容清空 , 然后按照set中的信号重新设置信号阻塞集 。相当于mask=set 。set:要操作的信号集地址 。若set为NULL,则不改变信号阻塞集合 , 函数只把当前信号阻塞集合保存到oldset中 。oldset: 保存原先信号阻塞集地址 。返回值:成功:0失败:-1未决信号集操作函数——sigpending:
#include<signal.h>int sigpending(sigset_t *set);功能:读取当前进程的未决信号集参数:set:未决信号集返回值:成功:0失败:-1代码示例:
实验一:把进程中信号屏蔽字2号信号进行阻塞,然后每隔1s对未决信号集进行打印,观察现象 。
#include <stdio.h>#include <unistd.h>#include <signal.h>void PrintPending(sigset_t* pend){int i = 0;for (i = 1; i < 32; ++i){if (sigismember(pend, i)){printf("1");}else{printf("0");}}printf("\n");}int main(){sigset_t set, oset;sigset_t pending;// 使用系统函数对信号集进行初始化sigemptyset(&set);sigemptyset(&oset);sigemptyset(&pending);// 阻塞2号信号// 先用系统函数对set信号集进行设置sigaddset(&set, 2);// 使用sigprocmask函数更改进程的信号屏蔽字// 第一个参数,三个选项:SIG_BLOCK(mask |= set) SIG_UNBLOCK(mask &= ~set) SIG_SETMASK(mask = set)sigprocmask(SIG_BLOCK, &set, &oset);int flag = 1; // 表示已经阻塞2号信号int count = 0;while (1){// 使用sigpending函数获取pending信号集sigpending(&pending);// 打印pending位图PrintPending(&pending);sleep(1);}return 0;}运行结果如下:
可以看到,进程收到2号信号时,且该信号被阻塞 , 处于未决状态,未决信号集中2号信号对应的比特位由0置1
二 Linux进程间通信

文章插图
实例2: 将上面的代码进行修改,进行运行10s后,我们将信号屏蔽字中2号信号解除屏蔽
【二 Linux进程间通信】#include <stdio.h>#include <unistd.h>#include <signal.h>void PrintPending(sigset_t* pend){int i = 0;for (i = 1; i < 32; ++i){if (sigismember(pend, i)){printf("1");}else{printf("0");}}printf("\n");}int main(){sigset_t set, oset;sigset_t pending;// 使用系统函数对信号集进行初始化sigemptyset(&set);sigemptyset(&oset);sigemptyset(&pending);// 阻塞2号信号// 先用系统函数对set信号集进行设置sigaddset(&set, 2);// 使用sigprocmask函数更改进程的信号屏蔽字// 第一个参数,三个选项:SIG_BLOCK(mask |= set) SIG_UNBLOCK(mask &= ~set) SIG_SETMASK(mask = set)sigprocmask(SIG_BLOCK, &set, &oset);int flag = 1; // 表示已经阻塞2号信号int count = 0;while (1){// 使用sigpending函数获取pending信号集 sigpending(&pending); // 打印pending位图 PrintPending(&pending); if (++count == 10){// 两种方法都可以sigprocmask(SIG_UNBLOCK, &set, &oset);//sigprocmask(SIG_SETMASK, &oset, NULL); }sleep(1);}return 0;}运行结果如下:
二 Linux进程间通信

文章插图
信号2被阻塞之后就变成了未决状态,当该信号从阻塞集合中解除的时候,该信号就会被处理,该信号被处理后 , 该信号的未决信号集的标志位将从1置为0 。

推荐阅读