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。

目录
相关文章
|
2月前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
104 3
|
2月前
|
监控 安全 Linux
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
88 2
|
18天前
|
存储 缓存 监控
Linux缓存管理:如何安全地清理系统缓存
在Linux系统中,内存管理至关重要。本文详细介绍了如何安全地清理系统缓存,特别是通过使用`/proc/sys/vm/drop_caches`接口。内容包括清理缓存的原因、步骤、注意事项和最佳实践,帮助你在必要时优化系统性能。
151 78
|
22天前
|
Linux Shell 网络安全
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验
本指南介绍如何利用 HTA 文件和 Metasploit 框架进行渗透测试。通过创建反向 shell、生成 HTA 文件、设置 HTTP 服务器和发送文件,最终实现对目标系统的控制。适用于教育目的,需合法授权。
54 9
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验
|
2月前
|
缓存 Java Linux
如何解决 Linux 系统中内存使用量耗尽的问题?
如何解决 Linux 系统中内存使用量耗尽的问题?
158 48
|
18天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
84 13
|
2月前
|
Ubuntu Linux 网络安全
linux系统ubuntu中在命令行中打开图形界面的文件夹
在Ubuntu系统中,通过命令行打开图形界面的文件夹是一个高效且实用的操作。无论是使用Nautilus、Dolphin还是Thunar,都可以根据具体桌面环境选择合适的文件管理器。通过上述命令和方法,可以简化日常工作,提高效率。同时,解决权限问题和图形界面问题也能确保操作的顺利进行。掌握这些技巧,可以使Linux操作更加便捷和灵活。
51 3
|
19天前
|
Ubuntu Linux C++
Win10系统上直接使用linux子系统教程(仅需五步!超简单,快速上手)
本文介绍了如何在Windows 10上安装并使用Linux子系统。首先,通过应用商店安装Windows Terminal和Linux系统(如Ubuntu)。接着,在控制面板中启用“适用于Linux的Windows子系统”并重启电脑。最后,在Windows Terminal中选择安装的Linux系统即可开始使用。文中还提供了注意事项和进一步配置的链接。
40 0
|
2月前
|
存储 运维 Linux
如何在 Linux 系统中使用 envsubst 命令替换环境变量?
`envsubst` 是 Linux 系统中用于替换文本中环境变量值的实用工具。本文分三部分介绍其工作原理、使用方法及实际应用,包括配置文件替换、脚本执行中环境变量替换和动态生成文件等场景,帮助用户高效利用 `envsubst` 进行开发和运维工作。
77 4
|
2月前
|
Linux
在 Linux 系统中,`find` 命令
在 Linux 系统中,`find` 命令
40 1