Linux绑定硬件IRQ到指定CPU核

在现在的多核处理器里,Linux下默认是将硬件IRQ分配到所有的CPU核心上,会优先使用第0核(即CPU0),那么我们要如何手动指定到某个或某几个核心上呢?这涉及到SMP IRQ Affinity

首先,我们可以通过如下命令cat /proc/interrupts来获取当前IRQ对应CPU核心的情况,我的电脑有如下返回值:

CPU0      CPU1      CPU2      CPU3      CPU4      CPU5      CPU6      CPU7
0:        17          0          0          0          0          0          0          0  IR-IO-APIC-edge      timer
1:          2          0          0          0          0          0          0          0  IR-IO-APIC-edge      i8042
7:          0          0          0          0          0          0          0          0  IR-IO-APIC-edge      parport0
8:          0          0          0          0          0          1          0          0  IR-IO-APIC-edge      rtc0
9:          0          0          0          0          0          0          0          0  IR-IO-APIC-fasteoi  acpi
12:          3          0          0          0          0          0          1          0  IR-IO-APIC-edge      i8042
16:        32          0          0          0          1          0          0          0  IR-IO-APIC-fasteoi  ehci_hcd:usb1
19:    7272446        193        135        74      1130        157        106        278  IR-IO-APIC-fasteoi  ata_piix, ata_piix
23:        32          0          0          0          1          0          0          0  IR-IO-APIC-fasteoi  ehci_hcd:usb2
40:          0          0          0          0          0          0          0          0  DMAR_MSI-edge      dmar0
41:          0          0          0          0          0          0          0          0  DMAR_MSI-edge      dmar1
42:          0          0          0          0          0          0          0          0  IR-PCI-MSI-edge      xhci_hcd
43:        614          9          1          1  18283973        19        10        12  IR-PCI-MSI-edge      eth0
44:          3        127          0          0        18        154          2        51  IR-PCI-MSI-edge      snd_hda_intel
45:        42          1          0          0          0          0          0          0  IR-PCI-MSI-edge      i915

NMI:      1075        823        812        812        774        816        804        802  Non-maskable interrupts
LOC:  14225495  10987071  12518753  12499043    4462117    3599360    3668949    3712199  Local timer interrupts
SPU:          0          0          0          0          0          0          0          0  Spurious interrupts
PMI:      1075        823        812        812        774        816        804        802  Performance monitoring interrupts
IWI:    668959    243175    173864    217368    333949    236190    164444    203926  IRQ work interrupts
RTR:          0          0          0          0          0          0          0          0  APIC ICR read retries
RES:    4325328    5435860    4978567    5009075    4562785    4288325    4511659    4408518  Rescheduling interrupts
CAL:      1766      5366      1609        985        608        327        290        282  Function call interrupts
TLB:    615205    531403    532879    503306    486281    510158    501906    511339  TLB shootdowns
TRM:          0          0          0          0          0          0          0          0  Thermal event interrupts
THR:          0          0          0          0          0          0          0          0  Threshold APIC interrupts
MCE:          0          0          0          0          0          0          0          0  Machine check exceptions
MCP:      4841      4841      4841      4841      4841      4841      4841      4841  Machine check polls
ERR:          0
MIS:          0

假如我们想修改RTC对应的响应处理器核心,那么我们可以先通过命令cat /proc/irq/8/smp_affinity来获得如下返回值(其中8为RTC对应的中断号,在上面的返回值第一列可以看到):

ff

那么表示8个核心都会被用到,而其对应关系为:

                     Binary          Hex
CPU0                  0000 0001        1
CPU1                  0000 0010        2
CPU2                  0000 0100        4
CPU3                  0000 1000        8
CPU4                  0001 0000      10
CPU5                  0010 0000      20
CPU6                  0100 0000      40
CPU7                  1000 0000      80

看出来了吧,将上面的值相加,就是16进制FF。

那么我们要设置IRQ到指定的CPU上面,可以使用如下命令:

echo "2" > /proc/irq/8/smp_affinity

上述命令将RTC的中断指定到CPU1核心上处理,也可以指定多个核心,如下:

echo "6" > /proc/irq/8/smp_affinity

将RTC中断指定到CPU1CPU2这两个核心上处理。

  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Linux 5.17.12 内版本中,可以通过修改 `pci_alloc_irq_vectors_affinity()` 函数的 `affinity_hint` 参数来 NVMe 驱动的所有 I/O 队列到同一 CPU 心上。 以下是示例代码: ```c static int nvme_setup_io_queues(struct nvme_dev *dev) { int err, qid; cpumask_var_t mask; // 分配 CPU 心亲和性掩码 mask = alloc_cpumask_var(GFP_KERNEL); if (!mask) return -ENOMEM; // 将所有 CPU 心添加到掩码中 cpumask_setall(mask); // 为每个 I/O 队列分配中断向量 for (qid = 0; qid < dev->ctrl.queue_count; qid++) { struct nvme_queue *nvmeq = &dev->queues[qid]; struct nvme_q_vector *q = &dev->q_vectors[qid]; struct pci_dev *pdev = to_pci_dev(dev->dev); irqreturn_t (*irq_fn)(int, void *); // 设置中断处理函数 irq_fn = nvme_irq; // 分配中断向量 err = pci_alloc_irq_vectors_affinity(pdev, 1, 1, PCI_IRQ_MSIX, q->num_vecs, mask, &q->affinity_hint); if (err < 0) { dev_err(dev->ctrl.device, "Failed to allocate IRQ vectors\n"); goto err_irq_vectors; } // I/O 队列和中断向量 nvmeq->cq_vector = q->cq_vector = q->affinity_hint; nvmeq->sq_vector = q->sq_vector = q->affinity_hint; err = request_irq(pci_irq_vector(pdev, q->affinity_hint), irq_fn, IRQF_SHARED, dev_name(dev->dev), nvmeq); if (err < 0) { dev_err(dev->ctrl.device, "Failed to request IRQ %d\n", pci_irq_vector(pdev, q->affinity_hint)); goto err_request_irq; } } free_cpumask_var(mask); return 0; err_request_irq: for (; qid >= 0; qid--) { struct nvme_q_vector *q = &dev->q_vectors[qid]; struct pci_dev *pdev = to_pci_dev(dev->dev); free_irq(pci_irq_vector(pdev, q->affinity_hint), &dev->queues[qid]); } err_irq_vectors: for (; qid >= 0; qid--) { struct nvme_q_vector *q = &dev->q_vectors[qid]; struct pci_dev *pdev = to_pci_dev(dev->dev); if (q->affinity_hint >= 0) pci_free_irq_vectors(pdev); } free_cpumask_var(mask); return err; } ``` 在此示例代码中,我们使用 `alloc_cpumask_var()` 函数来分配一个 CPU 心亲和性掩码,然后使用 `cpumask_setall()` 函数将所有 CPU 心添加到掩码中。接下来,我们使用 `pci_alloc_irq_vectors_affinity()` 函数为每个 I/O 队列分配中断向量,并将 `affinity_hint` 参数设置为掩码,以所有 I/O 队列到同一 CPU 心。最后,我们使用 `request_irq()` 函数将每个 I/O 队列和中断向量在一起,以便在中断处理程序中处理 I/O 完成事件。 请注意,NVMe 驱动的代码可能因版本而异,因此请根据您使用的内版本和驱动版本进行适当的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stxinu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值