Linux 信号生成和处理解释
信号是操作系统(包括 Linux)不可或缺的一部分。以下是 Linux 内核中信号生成和处理的基础知识。
Linux 内核中的信号机制允许正在运行的应用程序在新事件发生时异步通知系统。由于其性质,这种信号机制通常称为软件中断。就像硬件中断一样,信号会中断应用程序的正常流程,并且应用程序何时收到信号是不可预测的。
让我们深入研究 Linux 中的信号机制并了解幕后发生的事情。
Linux 中的基本信号概念
在 Linux 上,进程在三种基本情况下生成信号:
当硬件侧出现异常情况时。例如,您可以考虑诸如应用程序尝试访问允许的地址空间之外的区域(分段错误)或生成包含除零运算的机器代码等事件。
诸如用户在控制台上使用 Ctrl + C 或 Ctrl + Z 等组合键、调整控制台屏幕大小或发送终止信号等情况。
应用程序中设置的计时器到期、给予应用程序的 CPU 限制较高、数据到达打开的文件描述符等。
信号的概念从 Unix 的早期版本就已经存在了。以前,Unix 版本之间在信号处理方面存在一些差异。后来,随着信号管理的 POSIX 标准化,Linux 和其他 Unix 衍生品开始遵循这些标准。因此,您在某些文档中可能会遇到的 Unix 信号和 POSIX 信号的概念指出了差异。
信号编号
信号具有各种数值,从一开始。例如,信号 1 在几乎每个系统中都是HUP信号,或者信号 9 是KILL信号。
但是,当您在应用程序中使用信号时,强烈建议不要使用这些数字。对于 POSIX 信号,signal.h 文件应位于应用程序中,并且开发人员应使用相关数字的常量定义,如 SIGHUP、SIGKILL等代替。
如果您检查系统上的 /usr/include/signal.h 文件,您可以通过查看诸如 __USE_POSIX 等值的定义来查看附加操作和其他包含的文件文件中的 >、__USE_XOPEN、__USE_POSIX199309 等。您可以在 /usr/include/asm-generic/signal.h 文件中找到 Linux 系统上的可用信号号,无需将其直接包含在应用程序代码中。
信号生成和发送
信号的产生是由于事件而发生的。然而,将信号发送(递送)到相关应用程序并不与信号的生成同时发生。
对于要发送到应用程序的信号,应用程序当前必须正在运行并且具有 CPU 资源。因此,当相关应用程序在上下文切换之后再次开始工作时,就会向特定应用程序发送信号。
待定信号概念
在信号从产生到传输的过程中,信号处于待机状态。您可以从 /proc/PID/status 文件访问待处理信号的数量以及进程允许的待处理信号的数量。
# For a process with PID: 2299
cat /proc/2299/status
# Output
...
SigQ: 2/31630
...
信号屏蔽和阻塞
应用程序通常无法预测信号到达的确切时间。因此,在任何操作过程中都可能会发生一些严重的中断。这可能会给大规模应用带来重大问题。
为了防止像这样的一些不良情况,有必要使用信号掩码。因此,可以在关键操作之前阻止某些信号。在此阶段,完成关键部分并删除已定义的块非常重要。这个过程是应用程序开发人员应该注意的。
当应用程序阻塞一个信号时,产生的其他同类型信号将处于等待状态,直到解除阻塞。在应用程序中,一旦块被移除,也会提供待处理信号的发送。
这样,在正常使用中移除块后,在块时搁置的相同类型的信号仅发送到应用程序一次。对于实时信号,情况有所不同。
Linux 信号类型
默认操作可能会根据信号类型而有所不同。如果接收相应信号的应用程序没有信号处理函数,则执行默认操作。有时这意味着终止应用程序,有时意味着忽略信号。
有些信号无法在应用层捕获,这些信号总是执行默认操作(如 KILL 信号)。
除了导致应用程序终止的某些操作之外,还会生成核心转储文件。核心转储文件是通过将相关进程的虚拟内存表写入磁盘而创建的,可帮助用户在下一阶段的调试工具结束进程之前检查状态信息。
以下值基于示例性 MIPS 架构:
Signal | Number | Default Action | Can It Be Caught? |
---|---|---|---|
SIGHUP | 1 | Terminate application | Yes |
SIGINT | 2 | Terminate application | Yes |
SIGQUIT | 3 | Terminate application (core dump) | Yes |
SIGILL | 4 | Terminate application (core dump) | Yes |
SIGTRAP | 5 | Terminate application (core dump) | Yes |
SIGABRT | 6 | Terminate application (core dump) | Yes |
SIGFPE | 8 | Terminate application (core dump) | Yes |
SIGKILL | 9 | Terminate application | No |
SIGBUS | 10 | Terminate application (core dump) | Yes |
SIGSEGV | 11 | Terminate application (core dump) | Yes |
SIGSYS | 12 | Terminate application (core dump) | Yes |
SIGPIPE | 13 | Terminate application | Yes |
SIGALRM | 14 | Terminate application | Yes |
SIGTERM | 15 | Terminate application | Yes |
SIGUSR1 | 16 | Terminate application | Yes |
SIGUSR2 | 17 | Terminate application | Yes |
SIGCHLD | 18 | Ignore | Yes |
SIGTSTP | 20 | Stop | Yes |
SIGURG | 21 | Ignore | Yes |
SIGPOLL | 22 | Terminate application | Yes |
SIGSTOP | 23 | Stop | No |
SIGCONT | 25 | Continue if stopped | Yes |
SIGTTIN | 26 | Stop | Yes |
SIGTTOU | 27 | Stop | Yes |
SIGVTALRM | 28 | Terminate application | Yes |
SIGPROF | 29 | Terminate application | Yes |
SIGXCPU | 30 | Terminate application (core dump) | Yes |
SIGXFSZ | 31 | Terminate application (core dump) | Yes |
Linux 中信号的生命周期
信号经历三个阶段。它们主要在生产阶段由内核或任何进程产生,并由数字表示。它们工作起来轻快而快速,因为它们没有任何额外的负载。但如果你看看 POSIX 方面,你会发现实时信号可以传输额外的数据。
信号的交付阶段位于生产阶段之后。通常,信号会尽快从内核到达应用程序。然而,有时应用程序可能会在执行关键操作时阻塞信号。在这种情况下,信号将保持待定状态,直到交易发生。
与信号一样,进程也是 Linux 生态系统不可或缺的一部分。如果您计划成为 Linux 系统管理员,那么了解什么是进程以及它们如何工作至关重要。