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

有关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. http status 状态码汇总

    常见HTTP状态码 200 OK 301 Moved Permanently 302 Found 304 Not Modified 307 Temporary Redirect 400 Bad Req ...

  2. [普通平衡树splay]【学习笔记】

    参考: http://blog.csdn.net/clove_unique/article/details/50630280 gty课件 找一个好的风格太难了,自己习惯用struct,就强行用stru ...

  3. POJ1151Atlantis 矩形面积并[线段树 离散化 扫描线]

    Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21734   Accepted: 8179 Descrip ...

  4. NYOJ 762

    容斥原理 http://blog.csdn.net/shiren_bod/article/details/5787722

  5. [No000078]Python3 字符串操作

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- '''Python 字符串操作 string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分 ...

  6. 转:Eclipse Search Tips

    from:  https://github.com/ajermakovics/eclipse-instasearch/wiki/Eclipse-search-tips Eclipse Search T ...

  7. KVO设计模式

    一,概述 KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知.简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应 ...

  8. sqlserver 2008R2数据库迁移oracle

    x项目需要,将以前的sqlserver数据库迁移的oracle数据库中,由于以前对oracle只是在DML语句的步骤,所以总结一下这次遇到的问题以及具体步骤 1,oracle新建数据库 新建Oracl ...

  9. Python-11-RabbitMQ、Redis使用

    RabbitMQ RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列(M ...

  10. jquery easyui 1.4.1 验证时tooltip 的位置调整

    现象是在表单中如果显示两列控件,右边的控件是combo,combobox 等右边有按钮的,宽度为100%时,验证不通过的tooltip 显示位置不准确如下图所示 打开 jquery.easyui-1. ...