我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,也可以屏蔽某些信号,使其不能传递给进程。那么我们应该如何设定我们需要处理的信号,我们不需要处理哪些信号等问题呢?信号集函数就是帮助我们解决这些问题的。

有关Linux进程间使用信号通信的更多内容,可以参阅我的另一篇文章,Linux进程间通信 -- 信号量函数 signal()、sigaction()

下面是信号函数集:

1、int sigemptyset(sigset_t *set);

该函数的作用是将信号集初始化为空。

2、int sigfillset(sigset_t *set);

该函数的作用是把信号集初始化包含所有已定义的信号。

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

该函数的作用是把信号signo添加到信号集set中,成功时返回0,失败时返回-1。

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

该函数的作用是把信号signo从信号集set中删除,成功时返回0,失败时返回-1.

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

该函数的作用是判断给定的信号signo是否是信号集中的一个成员,如果是返回1,如果不是,返回0,如果给定的信号无效,返回-1;

6、int sigpromask(int how, const sigset_t *set, sigset_t *oset);

该函数可以根据参数指定的方法修改进程的信号屏蔽字。新的信号屏蔽字由参数set(非空)指定,而原先的信号屏蔽字将保存在oset(非空)中。如果set为空,则how没有意义,但此时调用该函数,如果oset不为空,则把当前信号屏蔽字保存到oset中。

how 的不同取值及操作如下所示:

如果sigpromask成功完成返回0,如果how取值无效返回-1,并设置errno为EINVAL。

注意:调用这个函数才能改变进程的屏蔽字,之前的函数都是为改变一个变量的值而已,并不会真正影响进程的屏蔽字。

7、int sigpending(sigset_t *set);

该函数的作用是将被阻塞的信号中停留在待处理状态的一组信号写到参数set指向的信号集中,成功调用返回0,否则返回-1,并设置errno表明错误原因。

8、int sigsuspend(const sigset_t *sigmask);

该函数通过将进程的屏蔽字替换为由参数sigmask给出的信号集,然后挂起进程的执行。注意操作的先后顺序,是先替换再挂起程序的执行。程序将在信号处理函数执行完毕后继续执行。如果接收到信号终止了程序,sigsuspend()就不会返回,如果接收到的信号没有终止程序,sigsuspend()就返回-1,并将errno设置为EINTR。

特别提醒:如果一个信号被进程阻塞,它就不会传递给进程,但会停留在待处理状态,当进程解除对待处理信号的阻塞时,待处理信号就会立刻被处理。

下面以一个例子来说明上述函数的用法,源文件为 sigset.c,代码如下:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>void handler(int sig)
{printf("Handle the signal %d\n", sig);
}int main(int argc, char **argv)
{sigset_t sigset;   // 用于记录屏蔽字sigset_t ign;     // 用于记录被阻塞(屏蔽)的信号集struct sigaction act;// 清空信号集sigemptyset(&sigset);sigemptyset(&ign);// 向信号集中添加 SIGINTsigaddset(&sigset, SIGINT);// 设置处理函数 和 信号集act.sa_handler = handler;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigaction(SIGINT, &act, 0);printf("Wait the signal SIGNAL...\n");pause();// 设置进程屏蔽字, 在本例中为屏蔽 SIGINTsigprocmask(SIG_SETMASK, &sigset, 0);printf("Please press Ctrl + C in 10 seconds...\n");sleep(10);// 测试 SIGINT 是否被屏蔽sigpending(&ign);if (sigismember(&ign, SIGINT)){printf("The SIGINT signal has ignored\n");}// 从信号集中删除信号 SIGINTsigdelset(&sigset, SIGINT);printf("Wait the signal SIGINT...\n");// 将进程的屏蔽字重新设置, 即取消对 SIGINT 的屏蔽// 并挂起进程sigsuspend(&sigset);printf("The app will exit in 5 secondes!\n");sleep(5);return 0;
}

运行结果如下:

首先,我们能过sigaction()函数改变了SIGINT信号的默认行为,使之执行指定的函数handler,所以输出了语句:Handle the signal 2。然后,通过sigprocmask()设置进程的信号屏蔽字,把SIGINT信号屏蔽起来,所以过了10秒之后,用sigpending()函数去获取被阻塞的信号集时,检测到了被阻塞的信号SIGINT,输出The SIGINT signal has ignored。最后,用函数sigdelset()函数去除先前用sigaddset()函数加在sigset上的信号SIGINT,再调用函数sigsuspend(),把进程的屏蔽字再次修改为sigset(不包含SIGINT),并挂起进程。由于先前的SIGINT信号停留在待处理状态,而现在进程已经不再阻塞该信号,所以进程马上对该信号进行处理,从而在最后,你不用输入 Ctrl+C 也会出现后面的处理语句(可参阅前面特别提醒的内容),最后过了5秒程序就成功退出了。

参考:

http://blog.csdn.net/ljianhui/article/details/10130539

《Linux 高性能服务器编程》

Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()...相关推荐

  1. 信号signal()、alarm()、信号集函数、sigprocmask()

    信号处理方式:     忽略 :但是SIGKEILL 和 SIGSTOP 不可以忽略:     捕捉信号: 但是不能捕捉 SIGKEILL 和 SIGSTOP :     执行默认操作: core文件 ...

  2. Linux进程间通信之信号

    一.信号 1.信号本质 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的,信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进 ...

  3. sigprocmask, sigpending, sigsuspend的用法

    sigset_t set sigemptyset(&set) :清空阻塞信号集合变量 sigfillset(&set) :添加所有的信号到阻塞集合变量里 sigaddset(& ...

  4. Linux系统无名管道通信实验,Linux进程间通信(二)---管道通信之无名管道及其基础实验...

    管道简介 管道是Linux中进程间通信的一种方式,它把一个程序的输出直接连接到另一个程序的输入(其实我更愿意将管道比喻为农村浇地的管子).Linux的管道主要包括两种:无名管道和有名管道.这一节主要讲 ...

  5. Linux进程间通信二 System V 消息队列简介与示例

    1. SystemV消息队列简介 消息队列,顾名思义即是存放消息的队列,内核为每个SystemV 维护了一个msg_queue的结构体,里面记录了每个消息队列的信息. struct msg_queue ...

  6. Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存

    Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存 参考:<linux编程从入门到精通>,<Linux C程序设计大全>,<unix环境高级编程> ...

  7. Linux系统编程(二)–信号

    文章目录 1 Hello signal 1.1 hello signal 程序 1.2 向 hello signal 发信号 1.3 招待你的"客人" 1.3.1 signal 函 ...

  8. 深入理解Linux进程间通信(IPC)-- 信号signal

    2. 信号(上) 2.1. 信号及信号来源 2.1.1 信号本质 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是异步的,一个进程不 ...

  9. 【linux系统编程】进程间通信:信号中断处理

    什么是信号? 信号是 Linux 进程间通信的最古老的方式.信号是软件中断,它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式 .信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断, ...

最新文章

  1. java 集合 自动排序的_java中的自动排序集合 ---- 20160809
  2. 求13-23+33……-1003(3.6)(Java)
  3. [置顶]       Mybatis技术(二) MyBatis-Spring
  4. 牛客 - 建通道(思维)
  5. Xamarin效果第一篇之时间轴
  6. 李晓菁201771010114《面向对象程序设计(java)》第十三周学习总结
  7. 【java基础知识】修改字符串的编码格式
  8. 笔者使用macOS的一些经验点滴记录1
  9. Linux下通过WebShell反弹Shell的技巧
  10. C#解析JSON字符串总结(转载)
  11. ARToolkit介绍
  12. java高级面试篇之redis面试收集总结/62题附答案)
  13. 同网段的VLAN隔离
  14. 安卓基础-day06-20180131
  15. GaRy-Liang的linux成长日记2-系统安装
  16. SSLOJ——P1738.水洼的大小
  17. 你还记得当年上课天天玩 JAVA游戏吗
  18. [NOIP2020] 微信步数
  19. 中小团队落地配置中心详解
  20. 笔记本光驱在计算机里不显示器,笔记本dvd光驱怎么播放蓝光_电脑如何播放蓝光碟图文步骤...

热门文章

  1. Generator的正确打开方式
  2. Git学习系列之Git基本操作提交项目(图文详解)
  3. NM-CIDS测试经历
  4. Linux使用logrotate来切割日志文件
  5. 前端开发js运算符单竖杠“|”的用法和作用及js数据处理
  6. nginx 稳定版 1.16.0 发布,支持动态加载 SSL 证书
  7. java日记(2)------定时任务quartz浅析
  8. 10-CSS基础-CSS选择器
  9. 广搜破解密码(HDU1195)
  10. Linux下查看文件或文件夹大小的命令df 、du、ls