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

有关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); // 向信号集中添加 SIGINT
sigaddset(&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(); // 设置进程屏蔽字, 在本例中为屏蔽 SIGINT
sigprocmask(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");
} // 从信号集中删除信号 SIGINT
sigdelset(&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. [转]Linux进程间通信——使用信号

    转载于:http://blog.csdn.net/ljianhui/article/details/10128731         经典!!! Linux进程间通信——使用信号 一.什么是信号 用过 ...

  2. Linux环境进程间通信(二):信号(下)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  3. Linux环境进程间通信(二): 信号(上)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  4. Linux进程间通信——使用信号

    一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...

  5. 练习--LINUX进程间通信之信号SIGNAL

    同样的,信号也不要太迷信可靠信号及不及靠信号,实时或非实时信号. 但必须要了解这些信号之间的差异,函数升级及参数,才能熟练运用. ~~~~~~~~~~~~~~~~ 信号本质 信号是在软件层次上对中断机 ...

  6. Linux 进程间通信(二) 管道

    Linux 进程间通信-管道 进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源.但是,进程不是孤立的,不同的进程之间需要信息的交换以及 ...

  7. sigprocmask, sigpending, sigsuspend的用法

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

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

    1.概述 通信方法 无法介于内核态与用户态的原因 管道(不包括命名管道) 局限于父子进程间的通信. 消息队列 在硬.软中断中无法无阻塞地接收数据. 信号量 无法介于内核态和用户态使用. 内存共享 需要 ...

  9. Linux进程间通信(三) - 信号

    什么是信号 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件.在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是进程间通 ...

随机推荐

  1. linux下更新python

    刚开始入门python,想直接入门python3,需要更新一下linux自带的python.自带的python是2.6,可以在终端root下键入python查看python版本. 1.从官网下载pyt ...

  2. python有超时的windows系统时间设置代码

    手边的笔记本用久了,cmos电池可能又没电了.每次开机时间都不对,导致访问一些有https的网页会出现警告信息. 于是找了找通过python脚本设置系统时间的方法,发现了两种,其一是调用socket直 ...

  3. P1546 最短网络 Agri-Net

    题目背景 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当然,他需要你的帮助. 题目描述 约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其 ...

  4. scp 上传文件到多个服务器节点

    参考:scp批量上传文件到多台机器上(升级版) 实测,代码可运行. 1.如果遇到syntax error near unexpected token问题,基本是由于windows环境下编写的shell ...

  5. JSON.net 在实体类中自定义日期的格式

    定义日期格式转换类,其继承 IsoDateTimeConverter,代码如下: public class DateTimeConverter : IsoDateTimeConverter { pub ...

  6. ajax返回值中有回车换行、空格的解决方法分享

    最近在写一个页面,用jquery ajax来实现判断,刚写好测试完全没有问题,过了两天发现出现问题,判断不成了.后来发现所有alert出来的返回值前面都会加若干换行和空格.(至今不明白,同一台电脑,同 ...

  7. [Leetcode] Course Schedule

    There are a total of n courses you have to take, labeled from 0 to n - 1. Some courses may have prer ...

  8. ExtJS4随笔(1) -- 在VS中加入Ext4的智能提示

    将辅助文件加入到Web工程内即可. 辅助文件

  9. 招聘前端、Java后端开发、测试、Mysql DBA

    公司介绍: http://www.lagou.com/gongsi/43095.html http://www.yamichu.com 简历发到: zhuye@yamichu.com 招聘职位: JA ...

  10. easyui 汇总

    1. easyui datagrid 表格组件列属性 formatter columns:{ { field:' product', title:'商品', align:'center', width ...