Linux系统编程之Linux 信号集编程:信号集的基本概念、用法和实现方式

简介: Linux系统编程之Linux 信号集编程:信号集的基本概念、用法和实现方式

信号集

表示多个信号的集合

信号在内核中的表示

信号递达(Delivery):实际执行信号处理的动作。

信号未决(Pending):信号从产生到递达之间的状态。

信号阻塞(Block)    :被阻塞的信号产生时将保持在未决状态,直到 进程解除对此信号的阻塞,才 执行递达的动作。

注意:

信号阻塞和信号忽略是不同的。只要信号被阻塞就不会递达,除非解除阻塞,而忽略是在递达之后 可选的一种处理动作。

一个信号处于Pending状态,屏蔽之后,它永远不会被Delivery 。

一个信号是否立即Delivery ,与Block没有绝对关

3张表的存储:

pending表:  用4个字节的位图表示,位图的位置表示信号编号,内容表示是否pending。

block表:      用4个字节的位图表示,位图的位置表示信号编号,内容表示是否block。

handler表:     是一个句柄函数指针,数组即可表示,下标表示信号编号,内容表示信号处理的动作,为NULL表示没有处理该信号。

分析上图中的信号:
1〉SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。
2〉SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。
3〉 SIGQUIT信号未产生过,一旦产生SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler。

 

信号集接口函数

sigemptyset      置空一个信号集
sigfillset           填充满一个信号集
sigaddset         将一个信号加入信号集
sigdelset        将一个信号从信号集删除
sigismember     检查一个信号集中是否有这个信号

  • 信号集增减操作
#include <signal.h>
 
    int sigemptyset(sigset_t *set);//将set集合置空
 
  int sigaddset(sigset_t *set,int signo);//将signo信号加入到set集合
  int sigdelset(sigset_t *set,int signo);//从set集合中移除signo信号
 
 
   int sigfillset(sigset_t *set); //将所有信号加入set集合
 

返回值:

        若成功,返回0

        若出错,返回-1

  • 测试信号是否已加入信号集
int sigismember(const sigset_t *set, int signum); //测试参数signum 代表的信号是否已加入至参数set信号集里

返回值:

        若成功,返回0

        若出错,返回-1

  • 设定对信号集处理方式
int sigdelset(sigset_t *set,int signo);
//设定对信号屏蔽集内的信号的处理方式(阻塞或不阻塞)。

参数:

how:用于指定信号修改的方式,可能选择有三种:

SIG_BLOCK //加入信号到进程屏蔽。

SIG_UNBLOCK //从进程屏蔽里将信号删除。

SIG_SETMASK //将set的值设定为新的进程屏蔽。

set:指向信号集的指针,在此专指新设的信号集,如果仅想读取现在的屏蔽值,可将其置为NULL。

oldset:也是指向信号集的指针,在此存放原来的信号集。

返回值:

        若成功,返回0

        若出错,返回-1,errno被设为EINVAL。

  • 等待信号
int sigsuspend(const sigset_t *sigmask);
 
//该函数通过将进程的屏蔽字替换为由参数sigmask给出的信号集,然后挂起进程的执行。注意操作的先后顺序,是先替换再挂起程序的执行。程序将在信号处理函数执行完毕后继续执行。
 
/*
sigsuspend的整个原子操作过程为:
(1) 设置新的mask阻塞当前进程;
(2) 收到信号,恢复原先mask;
(3) 调用该进程设置的信号处理函数;
(4) 待信号处理函数返回后,sigsuspend返回。
*/

参数说明

  sigmask 希望屏蔽的信号

返回值

       若接收到信号终止了程序,sigsuspend()就不会返回。

        若出错(接收到的信号没有终止程序),返回-1,并将errno设置为EINTR。  

使用场景:

   sigsuspend() 函数可以更改进程的信号屏蔽字可以阻塞所选择的信号,或解除对它们的阻塞,使用这种技术可以保护不希望由信号中断的代码临界区。

   如果希望对一个信号解除阻塞,然后pause等待以前被阻塞的信号发生,那么必须使用 sigsuspend() 函数, pause() 函数无法达成上述目的.

  • 阻塞信号
    if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
        err_sys("SIG_BLOCK error");
  • 解除阻塞
    if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
        err_sys("SIG_SETMASK error");
  • 等待信号
pause();
  • 检查和更改阻塞的信号
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
       /* Prototype for the underlying system call */
//可以根据参数指定的方法修改进程的信号屏蔽字。
//新的信号屏蔽字由参数set(非空)指定,而原先的信号屏蔽字将保存在oset(非空)中。
//如果set为空,则how没有意义,但此时调用该函数,如果oset不为空,则把当前信号屏蔽字保存到oset中。
 
/* 底层系统调用的原型 */
int rt_sigprocmask(int how, const kernel_sigset_t *set,kernel_sigset_t *oldset, size_t sigsetsize);
       /* Prototype for the legacy system call (deprecated) */
 
 
int sigpending(sigset_t *set);
//获取信号集,查询被搁置的信号

参数:

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

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

SIG_BLOCK :    附加set到阻塞表,原来的保存在到oldset

SIG_UNBLOCK:从阻塞表中删除set中的信号,原来的保存到oldset

SIG_SETMASK:清空阻塞表并设置为set,原来的保存到oldset

返回值:

       若成功,返回0

       若出错(how取值无效返回-1),返回-1,并设置errno为EINVAL。

目录
相关文章
|
1月前
|
存储 算法 Linux
【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构
【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构
46 0
|
3天前
|
消息中间件 关系型数据库 MySQL
Linux:开源之魅与编程之道
Linux:开源之魅与编程之道
11 1
|
4天前
|
NoSQL Linux 程序员
【linux进程信号(一)】信号的概念以及产生信号的方式
【linux进程信号(一)】信号的概念以及产生信号的方式
|
20天前
|
Linux 开发者
Linux文件编程(open read write close函数)
通过这些函数,开发者可以在Linux环境下进行文件的读取、写入和管理。 买CN2云服务器,免备案服务器,高防服务器,就选蓝易云。百度搜索:蓝易云
85 4
|
26天前
|
传感器 Linux API
嵌入式Linux串口编程简介
嵌入式Linux串口编程简介
19 1
|
26天前
|
Linux 测试技术 C语言
【Linux】应用编程之C语言文件操作
【Linux】应用编程之C语言文件操作
|
1月前
|
算法 Linux API
【Linux系统编程】一文了解 Linux目录的创建和删除API 创建、删除与读取
【Linux系统编程】一文了解 Linux目录的创建和删除API 创建、删除与读取
28 0
【Linux系统编程】一文了解 Linux目录的创建和删除API 创建、删除与读取
|
7天前
|
机器学习/深度学习 缓存 监控
linux查看CPU、内存、网络、磁盘IO命令
`Linux`系统中,使用`top`命令查看CPU状态,要查看CPU详细信息,可利用`cat /proc/cpuinfo`相关命令。`free`命令用于查看内存使用情况。网络相关命令包括`ifconfig`(查看网卡状态)、`ifdown/ifup`(禁用/启用网卡)、`netstat`(列出网络连接,如`-tuln`组合)以及`nslookup`、`ping`、`telnet`、`traceroute`等。磁盘IO方面,`iostat`(如`-k -p ALL`)显示磁盘IO统计,`iotop`(如`-o -d 1`)则用于查看磁盘IO瓶颈。
|
1天前
|
Linux
【Linux】深入理解ls命令
【Linux】深入理解ls命令
|
3天前
|
监控 Linux Windows
50个必知的Linux命令技巧,你都掌握了吗?(下)
50个必知的Linux命令技巧,你都掌握了吗?(下)