82. interrupts

中断,它是一种由设备使用的硬件资源异步向处理器发信号。实际上,中断就是由硬件来打断操作系统。 大多数现代硬件都通过中断与操作系统通信。对给定硬件进行管理的驱动程序注册中断处理程序,是为了响应并处理来自相关硬件的中断。中断过程所做的工作包括应答并重新设置硬件, 从设备拷贝数据到内存以及反之,处理硬件请求,并发送新的硬件请求。 《linux内核设计与实现》

不同设备的中断:

82.1. 解读中断

这里以树莓派的中断为例。

           CPU0       CPU1       CPU2       CPU3
 16:          0          0          0          0  bcm2836-timer   0 Edge      arch_timer
 17:    3047829    2104689    4451895    1361536  bcm2836-timer   1 Edge      arch_timer
 23:      15893          0          0          0  ARMCTRL-level   1 Edge      3f00b880.mailbox
 24:          2          0          0          0  ARMCTRL-level   2 Edge      VCHIQ doorbell
 46:          0          0          0          0  ARMCTRL-level  48 Edge      bcm2708_fb dma
 48:          0          0          0          0  ARMCTRL-level  50 Edge      DMA IRQ
 50:          0          0          0          0  ARMCTRL-level  52 Edge      DMA IRQ
 51:      35573          0          0          0  ARMCTRL-level  53 Edge      DMA IRQ
 54:        206          0          0          0  ARMCTRL-level  56 Edge      DMA IRQ
 59:          0          0          0          0  ARMCTRL-level  61 Edge      bcm2835-auxirq
 62:  139285704          0          0          0  ARMCTRL-level  64 Edge      dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1
 79:          0          0          0          0  ARMCTRL-level  81 Edge      3f200000.gpio:bank0
 80:          0          0          0          0  ARMCTRL-level  82 Edge      3f200000.gpio:bank1
 86:      21597          0          0          0  ARMCTRL-level  88 Edge      mmc0
 87:       5300          0          0          0  ARMCTRL-level  89 Edge      uart-pl011
 92:       4489          0          0          0  ARMCTRL-level  94 Edge      mmc1
FIQ:              usb_fiq
IPI0:          0          0          0          0  CPU wakeup interrupts
IPI1:          0          0          0          0  Timer broadcast interrupts
IPI2:     590271     437681    1438135     374644  Rescheduling interrupts
IPI3:         21         22        346         94  Function call interrupts
IPI4:          0          0          0          0  CPU stop interrupts
IPI5:     550412     395048    1834241     236945  IRQ work interrupts
IPI6:          0          0          0          0  completion interrupts
Err:          0

kernel/irq/proc.c 中的函数可以看到打印函数

int show_interrupts(struct seq_file *p, void *v)
前半部分
第一列:是中断号。
第二、三、四、五列:每列一个CPU,是在该CPU上的中断计数器。可以看到17号中断产生了非常多,它是时钟中断。
/* print header and calculate the width of the first column */
if (i == 0) {
        for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
                j *= 10;

        seq_printf(p, "%*s", prec + 8, "");
        for_each_online_cpu(j)
                seq_printf(p, "CPU%-8d", j);
        seq_putc(p, '\n');
}
第六列是中断控制器。[bcm2836]是树莓派2的CPU。bcm2836-timer是cpu时钟中断控制器。[ARMCTRL-level]是bcm2836的顶层中断控制器。
第七列:硬件中断号?
if (desc->irq_data.domain)
        seq_printf(p, " %*d", prec, (int) desc->irq_data.hwirq);
else
        seq_printf(p, " %*s", prec, "");

第八列:中断级别。

#ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL
        seq_printf(p, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge");
#endif

第九列:就是注册的终端处理程序。有多个逗号的表示这个中断号对应有多个中断处理程序。

action = desc->action;
if (action) {
        seq_printf(p, "  %s", action->name);
        while ((action = action->next) != NULL)
                seq_printf(p, ", %s", action->name);
}

dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1代表以太网或者USB中断 [x86云主机的中断]中的i8042代表键盘控制器中断 ##术语 IRQ 中断请求 ISR Interrupt Service Routine 中断服务例程