饰品网站模板建立网站的作用
在深入学习 Linux 时,我们会接触到几个概念: 硬中断、软中断、进程信号,但要搞清楚它们之间的关系并不容易。
本文将尝试通过介绍,客户端数据包如何一步步达到用户进程,阐述 中断 与 进程信号 是如何协作的。
1 什么是进程信号
进程信号 是一种特殊的 进程间通信(IPC,Inter-Process Communication)机制,是一种由操作系统提供的 异步通知机制,用来 在进程运行的任意时刻,将某些重要事件传递给它。
事件可能来自内核,如:
- 父进程在子进程退出时接收 SIGCHLD,以便回收资源;
- 非法内存访问。
也可能来自外部操作,如:
- 用户按下 Ctrl+C,终端会向前台进程组发送SIGINT,要求它中断执行;
- 系统管理员执行 kill -HUP pid,常用于通知守护进程重新加载配置。
收到信号的进程需要立即做出相应的处理:有些信号会终止进程,有些可以触发用户自定义的处理函数,还有一些可以被忽略。
通过信号,操作系统能够在关键时刻打断进程的正常执行,使进程具备 响应外部环境变化、实现进程间控制与协作 的能力。
2 中断
2.1 硬中断
硬中断 由硬件设备主动发起,是硬件向 CPU 传递 “紧急事件”,如数据接收完成、故障告警等的核心机制。
当硬件设备(如网卡、磁盘、键盘)完成操作或出现异常时,会通过硬件引脚向 CPU 发送中断请求信号(IRQ, Interrupt Request);一旦收到该信号,CPU 会立即暂停当前正在执行的任务 —— 无论此时运行的是用户态进程(如应用程序)还是内核态逻辑(如进程调度),并优先跳转至该中断对应的中断服务程序(ISR,Interrupt Service Routine) 执行。
由于 硬中断 的触发往往伴随硬件的 “即时需求”,ISR 的设计遵循 “极致精简” 原则:仅完成最核心的紧急操作,不涉及复杂逻辑,以此确保执行时间极短,避免长时间占用 CPU 而阻塞其他硬件的中断请求。
2.2 软中断
硬中断 的核心要求是 “快”, 中断服务程序 ISR 仅能完成诸如 数据搬运、状态标记 等不耗时的简单工作。而 软中断 是操作系统内核中承接硬中断 后续复杂处理 的核心机制。
软中断 的作用是:
- 内核级的异步任务队列,用于在不阻塞硬件响应的前提下,高效处理 硬中断触发的 非紧急但耗时 的业务逻辑;
- 介于 硬中断和普通内核或用户进程之间,平衡了系统的响应速度与处理效率。
3 硬中断、软中断 与 信号
接下来,我们将以 UDP 数据包到达用户进程的完整流程为切入点,深入剖析硬中断、软中断以及信号这三者之间是怎样协同工作的。
3.1 硬中断处理
当用户发送的数据包到达网络接口后,网络接口会先将数据包写入内存,随后触发硬中断,过程如下时序图:

- (1) 客户端发送数据包到服务器,服务器由网卡(NIC,Network Interface Card)接收数据;
- (2) 网卡接收数据包后,不需经过 CPU,直接通过 DMA(Direct Memory Access) 把数据写到内存;
- (3) 在接收到一定的数据包后,网卡通过 硬中断(IRQ) 通知CPU,有数据达到。我们可以通过ethtool命令,查看网卡发起硬中断的阈值:
  
 其中rx-usecs: 20,表示当收到第一个包后,网卡会延迟 最多 20 微秒 再触发中断,rx-frames: 5,表示如果累计 5 个数据包,无论时间是否达到rx-usecs,都会立即触发一次中断;
- (4) CPU 收到硬中断后,会停止当前在执行的内核进程或用户进程;
- (5) CPU 及时执行网卡驱动注册在内核的 ISR;
- (6) ISR 发起软中断,之后,软中断处理函数将进行后续的处理,至此,硬中断完成。
3.2 软中断与信号
硬中断 发生后,后续的处理工作会由 软中断 服务程序(ISR)来完成。在软中断服务程序处理完毕后:
- 若用户进程正因等待数据而处于阻塞状态,例如执行了 recv ()调用,内核会直接将其唤醒,使其可以继续运行并读取数据;
- 若用户进程已通过 fcntl函数配置了O_ASYNC, 异步 I/O 模式 和F_SETOWN, 指定信号接收进程,则内核会发送SIGIO信号,以此通知进程 “数据已就绪”。
处理时序图如下(图中省略了部分细节,仅为展示整体处理流程):

- (7) 软中断由 ksoftirqd(全称 Kernel Soft IRQ Daemon)进程处理。ksoftirqd是内核的 daemon 进程,每个CPU核对应一个ksoftirqd进程。如下图,服务器有 8 个核,则有 8 个ksoftirqd进程与之绑定:
  
 由于本次软中断由网卡驱动发起,因此ksoftirqd会调用网络模块的net_rx_action(rx为receive,接收数据的意思) 函数;
- (8) net_rx_action会调用网卡驱动的poll函数;
- (9) poll函数会读取网卡写到内存中的数据包,并把数据包转换为skb格式。skb是 Linux 内核中用于管理网络数据包的数据结构格式,其全称为Socket Buffer, 套接字缓冲区;
- (10) 网卡驱动模块调用 napi_gro_receive函数,skb数据包将进入网络协议栈;
- (11) skb逐层经过2层协议(以太网)、3层协议(IP)、4层协议(TCP/UDP) 协议栈,最终匹配到对应的用户态socket,数据写入socket接收缓冲区;
- (12) 若用户进程因等待数据阻塞,如recv()调用,内核直接唤醒进程;若用户进程通过fcntl配置了O_ASYNC, 异步 I/O 和F_SETOWN,指定信号接收进程 时,内核会发送SIGIO信号,通知进程 “数据已就绪”;
- (13) 用户进程从 Socket 缓冲区读取数据,继续业务逻辑处理。
3.3 总结整个处理流程
网卡接收数据包 -> 网卡驱动处理硬中断并触发 NET_RX_SOFTIRQ 软中断 -> ksoftirqd 检测到软中断并执行 net_rx_action 函数 -> 从 softnet_data.input_pkt_queue 取出 skb 交由 TCP/IP 协议栈逐层解析 -> 协议栈将数据写入目标 socket 接收缓冲区 -> 若用户进程阻塞于 recv () 则内核直接唤醒进程,若配置 O_ASYNC+F_SETOWN 则内核信号子系统向用户进程发送 SIGIO 信号。
