信号集,信号屏蔽字,捕捉信号

本文详细介绍了信号、信号集的概念,包括信号的阻塞、未决状态和处理方式。讨论了内核如何表示信号,以及信号在进程PCB中的表示。重点讲述了如何使用sigset_t进行信号集操作,如`sigemptyset`、`sigfillset`等函数,并讲解了`sigprocmask`用于读取和修改信号屏蔽字,以及`sigpending`用于获取进程的未决信号集。此外,文章还探讨了信号的捕捉机制,包括`signal`和`sigaction`函数,如何设置自定义信号处理函数,并展示了相关代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一,信号,信号集

1. 信号相关的概念

        信号递达:实际执行信号的处理动作

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

        信号阻塞:如果一个信号被阻塞,那它在产生时处于未决状态,不会被递达,只有解除该信号后,才被递达。

注意:信号的阻塞,是还未执行处理动作,而信号的忽略是正在处理信号,但信号的处理动作是忽略。这两者是不同的。

2. 信号在内核中的表示

        我们之前一直说操作系统向进程发送了一个信号,但操作系统是如何发送的,见下图:


        上图应该横向来看,每一行表示一种信号。上图表明,在每个进程的PCB中都有一个有关信号的指针,该指针指向一张表,该表中有三部分内容:

block位图:表示每种信号是否被阻塞,0表示没有被阻塞,1表示被阻塞。

pending位图:表示每种信号的未决状态,1表示该信号已经已经产生,但还未递达。0表示信号没有产生,或者产生后已经递达了,此时该标志位也变为0。

handler表:实际是一函数指针数组,数组每个元素对应处理该信号的函数指针。如果是SIG_DEL表示自行默认处理动作,如果是SIG_IGN表示忽略该信号,如果是用户自定义处理动作,则保存的是自定义函数的指针,该自定义函数位于用户空间中。

        因此,操作系统向进程发送信号是指将该表中的pending位图中的该信号对应状态位由0变为1。如果该信号的block标志位为1,表明该信号被阻塞,所以不会被递达,只有解除阻塞后才会递达。用户可以通过修改handler表中该信号对应的函数指针。当接收到该信号时,来执行自定义处理动作,这就叫信号的捕捉。

        常规信号在递达前产生多次时,只会被记一下,而实时信号可以将其全部放入一个队列中。这里只讨论常规信号。

二, 信号集及相关操作函数

        上面我们已经了解了操作系统是如何发送信号的。当我们使用触发或采取二中信号产生的条件时,操作系统会将pending表中对应的比特位由0变为1来产生信号。也就是说pending表是由操作系统来修改的。如果我们想阻塞某种信号,就必须人为的对block表中的比特位进行修改,以及想知道pending表和block表中的相关内容,这些又如何做到呢?

1. 信号集sigset_t

        我们要查看或修改block表,首先要知道它是如何存储的,即它是什么类型的。从上图中可以看到,pending表和block表的结构很相似,都是一个比特位表示一种信号的未决或阻塞状态。所以,所有信号的未决状态信息和阻塞状态信息,可以用同一种类型来存储,这个类型就叫做信号集sigset_t。阻塞信号集也叫作信号屏蔽字。

2. 信号集操作函数

        知道了block表和pending表的存储类型,便可以对其查询和修改了。sigset_t类型内部是如何存储这些比特位的,这些我们是不必关心的。如果是一个整型变量,可以直接对其赋值进行修改。而sigset_t类型的变量必须通过调用以下函数来实现:

        注意:对sigset_t类型的变量进行查看或修改只能通过调用以下函数,而直接printf打印该类型的变量是没有意义的</

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值