FreeBSD 信号管理

本文介绍了FreeBSD操作系统中信号管理的原理和机制,信号作为进程间通信的一种方式,其处理涉及信号屏蔽、默认处理程序、自定义信号处理程序以及与硬件中断的类比。通过sigaction、sigprocmask等系统调用,进程可以指定信号处理方式,包括忽略、捕获和恢复等。不能被忽略或捕获的信号如SIGSTOP和SIGKILL确保了系统的控制能力。此外,文章还讨论了信号的传递、线程间的信号处理以及与用户态栈的交互。
摘要由CSDN通过智能技术生成

参考书籍 The Design and Implementation of the FreeBSD Operating System by Marshall Kirk McKusick, George V. Neville-Neil, and Robert N.M. Watson. 2nd edition, Chapter 4, Process Management – 4.7 Signals.

信号最初是用来为特殊事件建立的模型,比如一个用户要强制结束一个逃逸程序。当时的设计并没有把信号作为一种进程之间通信的机制,因此并没有多少人关心他的可靠性。在早期的系统中,如果一个信号被捕获,其对应的处理是重置为默认的操作。

当前FreeBSD中的信号系统是建立在一个虚拟机模型(virtual machine model)之上的。在该模型中,系统调用被视作与硬件指令是相同类型的操作。信号是该模型中与硬件陷阱和中断相对应的机制。只不过信号是软件实现的。信号处理程序与陷阱/中断处理程序具有相同的机制。类似于硬件中可以屏蔽中断来保证数据访问的一致性,软件实现的信号也可以被屏蔽。最后,同中断处理类似,有些信号处理程序要求复杂的运行时栈环境,特定的信号处理可以有选择的借助应用在用户空间提供的运行栈。

硬件机器软件虚拟机
指令集系统调用集
可重启指令可重启的系统调用
中断/陷阱信号
中断/陷阱处理程序信号处理程序
中断屏蔽信号屏蔽
中断栈信号栈

Table: 硬件系统操作与软件虚拟机系统操作的对比。

信号处理是按照每个进程为单位进行的。如果一个进程没有制定如何处理一个信号,则对该信号采取默认处理程序。默认处理程序可以是:

  • 忽略
  • 终止(terminating) 进程中所有线程
  • 在生成core file后终止(terminating) 进程中的所有线程
  • 强制退出(stopping) 进程中的所有线程
  • 恢复进程中的所有线程

一个应用程序可以通过sigaction系统调用来指定某个信号的处理程序,这些程序包括:

  • 采取默认操作
  • 忽略
  • 使用指定信号处理程序(signal handler)

信号处理程序(signal handler)是一个系统调用可以调用的用户态程序。一般称信号处理程序捕获一个信号。SIGSTOP 和 SIGKILL 两个信号是无法屏蔽,忽略,或者捕获的。这样的限制保证了这两个信号可以用于stop或kill逃逸程序。

当系统检测到事件发生时,系统可以发送信号通知进程。这样的事件包括硬件事件,如非法指令,和软件事件,如终端发送的终止请求。一个进程可以通过kill系统调用给另一个进程发送信号。一个发送信号的进程仅仅能发送给具有相同有效用户标识(effective user identifier)的其他进程发送信号,即一个用户的进程无法发送信号给另一个用户的进程,除非该用户是超级用户。唯一的一个特例是continue信号 SIGCONT。该信号可以发送给当前发送者进程的所有子进程。保留这样一个特例的原因是允许用户在用键盘停止setuid程序后能够重启该程序。

系统调用sigprocmask可供每个线程用来屏蔽信号的传送(delivery)。如果一个线程的信号被屏蔽,该信号被存储在该线程的等待信号队列(pending signals)中,该队列中的信号不会被处理,除非信号被解屏蔽。sigprocmask可以修改线程的等待信号队列。它可以向队列中增加新的屏蔽信号,删除已屏蔽信号,或者替换屏蔽信号。

Although the delivery of the SIGCONT signal to the signal handler of a process may be masked, the actions of resuming that stopped process is not masked.

另外两个信号相关的系统调用是sigsuspendsigaltstacksigsuspend 允许当前进程主动放弃CPU,直到该进程收到信号为止。类似于**sleep()**方法。sigaltstack 允许当前进程指定一个用于信号处理的运行栈。默认情况下,操作系统会用进程正常使用的运行栈处理信号。在一些程序中,这个默认栈是不可行的。比如,如果一个程序有较多的线程,每一个都有自己的运行栈,那么在每一个运行栈中预留信号处理的栈空间会导致浪费。这时让所有线程都使用同一个足够大的运行栈处理信号,会提高内存使用效率。

最后一个信号相关的系统调用是sigreturnsigreturn等同于用户态的load-process-context操作。用户程序通过该系统调用传送给内核一个指针。指针指向一个存储着线程的上下文运行环境的内存块。在用户的信号处理程序完成后,sigreturn使用该内存块恢复线程的正常运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值