09 | 软中断

225 阅读2分钟

1. 概述

中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力。Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部:

  • 上半部用来快速处理中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关的或时间敏感的工作。
  • 下半部用来延迟处理上半部未完成的工作,通常以内核线程的方式运行。

举个最常见的网卡接收数据包的例子。当网卡接收到数据包时,会通过硬件中断通知内核。内核响应这个中断,分为两个阶段:上半部下半部

上半部(硬中断):

  • 任务:快速处理硬件请求。
  • 过程:网卡的数据被读到内存中,硬件寄存器的状态被更新,随后发送软中断信号通知下半部进行进一步处理。
  • 特点:上半部的处理必须尽快完成,以避免阻塞其他硬件中断,因此执行时间较短。

下半部(软中断):

  • 任务:处理更复杂的工作,比如从内存中解析网络数据,逐层处理网络协议栈,最终将数据交给应用程序。
  • 过程:由软中断内核线程(如 ksoftirqd/0)唤醒执行。每个 CPU 都有一个对应的软中断线程。
  • 特点:软中断通常是延迟执行的,它不立即响应硬件请求,而是稍后在空闲时处理任务。

总结:

  • 上半部(硬中断)快速响应硬件事件并完成基本处理。
  • 下半部(软中断)延迟执行,处理更复杂的任务,通常由 ksoftirqd 线程执行。

软中断不仅仅处理硬件中断的下半部,还包括内核调度、RCU 锁等任务。

如何查看?

  • /proc/softirqs 提供了软中断的运行情况;
  • /proc/interrupts 提供了硬中断的运行情况。

软中断

$ cat /proc/softirqs
                    CPU0       CPU1
          HI:          0          0
       TIMER:     811613    1972736
      NET_TX:         49          7
      NET_RX:    1136736    1506885
       BLOCK:          0          0
    IRQ_POLL:          0          0
     TASKLET:     304787       3691
       SCHED:     689718    1897539
     HRTIMER:          0          0
         RCU:    1330771    1354737

硬中断

root@calvin:~# cat /proc/interrupts
           CPU0       CPU1
  1:          9          0   IO-APIC   1-edge      i8042
  6:         23          0   IO-APIC   6-edge      floppy
  8:          0          0   IO-APIC   8-edge      rtc0
  9:          1          0   IO-APIC   9-fasteoi   acpi
 12:          0        163   IO-APIC  12-edge      i8042
 14:          0          0   IO-APIC  14-edge      ata_piix
 15:      49863          0   IO-APIC  15-edge      ata_piix
NMI:          0          0   Non-maskable interrupts
LOC:        440        366   Local timer interrupts
SPU:          0          0   Spurious interrupts
PMI:          0          0   Performance monitoring interrupts
IWI:        387        355   IRQ work interrupts
RTR:          0          0   APIC ICR read retries
RES:    7176138    8463277   Rescheduling interrupts
CAL:       6861       6039   Function call interrupts
TLB:          0          0   TLB shootdowns
TRM:          0          0   Thermal event interrupts
THR:          0          0   Threshold APIC interrupts
DFR:          0          0   Deferred Error APIC interrupts
MCE:          0          0   Machine check exceptions
MCP:        161        161   Machine check polls
HYP:    6926152    4474577   Hypervisor callback interrupts
ERR:          0
MIS:          0
PIN:          0          0   Posted-interrupt notification event
NPI:          0          0   Nested posted-interrupt event
PIW:          0          0   Posted-interrupt wakeup event

软中断的注意事项

  1. 软中断的类型
    • 软中断分为多种类型,每种类型对应不同的工作任务。常见类型包括:
      • NET_RX:网络接收中断。
      • NET_TX:网络发送中断。
    • 每种软中断类型都负责不同的工作,通常通过第一列标识。
  1. 软中断在不同 CPU 上的分布
    • 同一种软中断通常在不同 CPU 上的分布应该大致相同,累积次数相差不大。例如,NET_RX 在 CPU0 和 CPU1 上的中断次数应该差不多。
    • 如果分布不均,可能说明某些 CPU 在处理软中断时不平衡。
  1. TASKLET 机制
    • TASKLET 是一种常用的软中断实现机制。每个 TASKLET 只会在其调用所在的 CPU 上执行一次。
    • 问题
      • 调度不均衡:由于 TASKLET 只在一个 CPU 上运行,可能导致负载不均衡。
      • 并行性问题:只能在单个 CPU 上运行,限制了并行处理能力,影响性能。
  1. 软中断内核线程(ksoftirqd)
    • 每个 CPU 上都对应一个软中断内核线程,线程名称为 ksoftirqd/CPU 编号(例如,ksoftirqd/0 对应 CPU 0)。
    • ksoftirqd 负责执行软中断任务,确保软中断得以处理。

查看软终端线程运行状态

$ ps aux | grep softirq
root         7  0.0  0.0      0     0 ?        S    Oct10   0:01 [ksoftirqd/0]
root        16  0.0  0.0      0     0 ?        S    Oct10   0:01 [ksoftirqd/1]