/proc/interrupts - 读入 c 显示没有 IPI

/proc/interrupts - Read in c shows no IPIs

当我cat /proc/interrupts时,我还可以看到系统内部中断(如doc中所述),例如核心上发生的所有 IPI。

但是,当我用C读/proc/interrupts的内容时,这些额外的行是没有的。例如。此代码:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char **argv)
{
        int source, n;
        unsigned char buffer[8192];

        source = open("/proc/interrupts", O_RDONLY);
        n=read(source, buffer, 8192);
        close(source);
        buffer[n] = 0;

        printf("%d chars in /proc/interrupts:\n", n);
        printf("%s", buffer);

        return 0;
}

提供与 cat 相同的输出,除了最后缺少有关 IPI 的行。为什么我的 C 代码无法读取 IPI 行,我该如何解决?

编辑:添加两种不同方法的输出

uuser@mpsoc:~/git/rt-benchmarking/ARM64/tif$ cat /proc/interrupts
           CPU0       CPU1       CPU2       CPU3
  3:   64464514   20153532     359399     132413     GICv2  30 Level     arch_timer
  6:          0          0          0          0     GICv2  67 Level     zynqmp_ipi
  7:          0          0          0          0     GICv2 175 Level     arm-pmu
  8:          0          0          0          0     GICv2 176 Level     arm-pmu
  9:          0          0          0          0     GICv2 177 Level     arm-pmu
 10:          0          0          0          0     GICv2 178 Level     arm-pmu
 13:          0          0          0          0     GICv2 156 Level     zynqmp-dma
 14:          0          0          0          0     GICv2 157 Level     zynqmp-dma
 15:          0          0          0          0     GICv2 158 Level     zynqmp-dma
 16:          0          0          0          0     GICv2 159 Level     zynqmp-dma
 17:          0          0          0          0     GICv2 160 Level     zynqmp-dma
 18:          0          0          0          0     GICv2 161 Level     zynqmp-dma
 19:          0          0          0          0     GICv2 162 Level     zynqmp-dma
 20:          0          0          0          0     GICv2 163 Level     zynqmp-dma
 22:          0          0          0          0     GICv2 109 Level     zynqmp-dma
 23:          0          0          0          0     GICv2 110 Level     zynqmp-dma
 24:          0          0          0          0     GICv2 111 Level     zynqmp-dma
 25:          0          0          0          0     GICv2 112 Level     zynqmp-dma
 26:          0          0          0          0     GICv2 113 Level     zynqmp-dma
 27:          0          0          0          0     GICv2 114 Level     zynqmp-dma
 28:          0          0          0          0     GICv2 115 Level     zynqmp-dma
 29:          0          0          0          0     GICv2 116 Level     zynqmp-dma
 30:          1          0          0          0     GICv2 144 Level     fd070000.memory-controller
 31:          0          0          0          0     GICv2  89 Level     eth0, eth0
 32:    9075012          0          0          0     GICv2  95 Level     eth1, eth1
 34:          0          0          0          0     GICv2  49 Level     cdns-i2c
 35:          0          0          0          0     GICv2  50 Level     cdns-i2c
 36:          0          0          0          0     GICv2  42 Level     ff960000.memory-controller
 37:          0          0          0          0     GICv2  57 Level     axi-pmon, axi-pmon
 38:          0          0          0          0     GICv2 155 Level     axi-pmon, axi-pmon
 39:       6215          0          0          0     GICv2  47 Level     ff0f0000.spi
 40:          0          0          0          0     GICv2  58 Level     ffa60000.rtc
 41:          0          0          0          0     GICv2  59 Level     ffa60000.rtc
 42:        674          0          0          0     GICv2  80 Level     mmc0
 43:     439018          0          0          0     GICv2  81 Level     mmc1
 44:          0          0          0          0     GICv2  51 Level     ff040000.spi
 45:          0          0          0          0     GICv2  52 Level     ff050000.spi
 46:        300          0          0          0     GICv2  53 Level     xuartps
 48:          0          0          0          0     GICv2  88 Level     ams-irq
 49:         12          0          0          0     GICv2 154 Level     fd4c0000.dma
 50:          0          0          0          0     GICv2 151 Level     fd4a0000.zynqmp-display
 51:          0          0          0          0     GICv2  97 Level     xhci-hcd:usb1
IPI0:   2913422    5267435   34552519   34586268       Rescheduling interrupts
IPI1:    146402     147211      18371      29840       Function call interrupts
IPI2:         0          0          0          0       CPU stop interrupts
IPI3:         0          0          0          0       CPU stop (for crash dump) interrupts
IPI4:         0          0          0          0       Timer broadcast interrupts
IPI5:     28636        345        203        125       IRQ work interrupts
IPI6:         0          0          0          0       CPU wake-up interrupts
Err:          0
uuser@mpsoc:~/git/rt-benchmarking/ARM64/tif$ ./a.out
3626 chars in /proc/interrupts:
           CPU0       CPU1       CPU2       CPU3
  3:   64465302   20153650     359399     132413     GICv2  30 Level     arch_timer
  6:          0          0          0          0     GICv2  67 Level     zynqmp_ipi
  7:          0          0          0          0     GICv2 175 Level     arm-pmu
  8:          0          0          0          0     GICv2 176 Level     arm-pmu
  9:          0          0          0          0     GICv2 177 Level     arm-pmu
 10:          0          0          0          0     GICv2 178 Level     arm-pmu
 13:          0          0          0          0     GICv2 156 Level     zynqmp-dma
 14:          0          0          0          0     GICv2 157 Level     zynqmp-dma
 15:          0          0          0          0     GICv2 158 Level     zynqmp-dma
 16:          0          0          0          0     GICv2 159 Level     zynqmp-dma
 17:          0          0          0          0     GICv2 160 Level     zynqmp-dma
 18:          0          0          0          0     GICv2 161 Level     zynqmp-dma
 19:          0          0          0          0     GICv2 162 Level     zynqmp-dma
 20:          0          0          0          0     GICv2 163 Level     zynqmp-dma
 22:          0          0          0          0     GICv2 109 Level     zynqmp-dma
 23:          0          0          0          0     GICv2 110 Level     zynqmp-dma
 24:          0          0          0          0     GICv2 111 Level     zynqmp-dma
 25:          0          0          0          0     GICv2 112 Level     zynqmp-dma
 26:          0          0          0          0     GICv2 113 Level     zynqmp-dma
 27:          0          0          0          0     GICv2 114 Level     zynqmp-dma
 28:          0          0          0          0     GICv2 115 Level     zynqmp-dma
 29:          0          0          0          0     GICv2 116 Level     zynqmp-dma
 30:          1          0          0          0     GICv2 144 Level     fd070000.memory-controller
 31:          0          0          0          0     GICv2  89 Level     eth0, eth0
 32:    9075115          0          0          0     GICv2  95 Level     eth1, eth1
 34:          0          0          0          0     GICv2  49 Level     cdns-i2c
 35:          0          0          0          0     GICv2  50 Level     cdns-i2c
 36:          0          0          0          0     GICv2  42 Level     ff960000.memory-controller
 37:          0          0          0          0     GICv2  57 Level     axi-pmon, axi-pmon
 38:          0          0          0          0     GICv2 155 Level     axi-pmon, axi-pmon
 39:       6215          0          0          0     GICv2  47 Level     ff0f0000.spi
 40:          0          0          0          0     GICv2  58 Level     ffa60000.rtc
 41:          0          0          0          0     GICv2  59 Level     ffa60000.rtc
 42:        674          0          0          0     GICv2  80 Level     mmc0
 43:     439018          0          0          0     GICv2  81 Level     mmc1
 44:          0          0          0          0     GICv2  51 Level     ff040000.spi
 45:          0          0          0          0     GICv2  52 Level     ff050000.spi
 46:        300          0          0          0     GICv2  53 Level     xuartps
 48:          0          0          0          0     GICv2  88 Level     ams-irq
 49:         12          0          0          0     GICv2 154 Level     fd4c0000.dma
 50:          0          0          0          0     GICv2 151 Level     fd4a0000.zynqmp-display
 51:          0          0          0          0     GICv2  97 Level     xhci-hcd:usb1

您正在寻找的是 IPI 中断向量计数的 RES/CAL 行。

典型的 SMP Linux(v3.10) 具有很少的 IPI 中断向量,如下所示和相应的处理程序。一个是重新调度,另外两个是使接收 CPU 到 运行 函数通过。正如我们所见,所有三个向量事件都有各自的计数器,并在过程级别显示为 RES/CAL.

RES:    2714120    2132494    1806195    1827171    1204178    1184985    1135312    1194862   Rescheduling interrupts
CAL:     311349     239698     256054     260474     201761     185813     227458     186660   Function call interrupts


#define RESCHEDULE_VECTOR       0xfd
#define CALL_FUNCTION_VECTOR        0xfc
#define CALL_FUNCTION_SINGLE_VECTOR 0xfb

#ifdef CONFIG_SMP
 apicinterrupt CALL_FUNCTION_SINGLE_VECTOR \
    call_function_single_interrupt smp_call_function_single_interrupt
 apicinterrupt CALL_FUNCTION_VECTOR \
    call_function_interrupt smp_call_function_interrupt
 apicinterrupt RESCHEDULE_VECTOR \
    reschedule_interrupt smp_reschedule_interrupt
#endif

#ifdef CONFIG_SMP
    unsigned int irq_resched_count;
    unsigned int irq_call_count;
#endif

#ifdef CONFIG_SMP
    seq_printf(p, "%*s: ", prec, "RES");
    for_each_online_cpu(j)
        seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
    seq_printf(p, "  Rescheduling interrupts\n");
    seq_printf(p, "%*s: ", prec, "CAL");
    for_each_online_cpu(j)
       seq_printf(p, "%10u ", irq_stats(j)->irq_call_count -
                irq_stats(j)->irq_tlb_count);
    seq_printf(p, "  Function call interrupts\n");
#endif 

解决方案是连续两次从打开的文件描述符中读取,即使在第一次迭代时没有读取完整的缓冲区。 cat 也是这样做的。因此,以下代码将产生所需的输出:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char **argv)
{
        int source, n;
        unsigned char buffer[8192];

        source = open("/proc/interrupts", O_RDONLY);
        for(int i = 0; i < 2; i++)
        {
                n=read(source, buffer, 8192);
                buffer[n] = 0;
                printf("%d chars in /proc/interrupts:\n", n);
                printf("%s", buffer);
        }

        close(source);

        return 0;
}