0

这些天,我正在研究内核内部网络代码,尤其是RPS代码。你知道,有很多关于它的功能。但我主要关注一些关于SMP 队列处理的功能,例如enqueue_to_backlogprocess_backlog.

enqueue_to_backlog我想知道通过使用两个函数 -和-来同步两个内核(或单核)process_backlog

在该函数中,A core(A) 持有spin_lock另一个 core(B) 的 a,用于将数据包排队进入input_pkt_queue并调度 core(B) 的 napi。并且A Core(B) 还拥有一个spin_lock用于拼接input_pkt_queueprocess_queuecore(B) 并自行删除 napi 时间表。我知道spin_lock应该保留以防止两个核心在处理队列期间相互访问同一个队列。

但我不明白为什么spin_locklocal_irq_disable(或local_irq_save)调用。我认为rps_lock当中断(TH)抢占当前上下文(softirq,BH)时,中断上下文(TH)无法访问队列或核心(B)。- 当然,可以访问 napi 结构以通过 TH 调度 napi,但它会禁用 irq,直到排队数据包 -所以我想知道为什么spin_lock使用 irq disable 调用。

我认为其他 BH(例如 tasklet)不可能抢占当前上下文(napi,softirq)。这是真的吗?而且我想知道 local_irq_disable 是禁用所有核心 irq 还是仅从字面上禁用当前核心的 irq?实际上,我读过一本关于内核开发的书,但我认为我对抢占的理解不够。

能解释一下为什么 rps 程序使用spin_lockwith的原因local_irq_disable吗?

4

1 回答 1

0

禁用中断会影响当前内核(仅)。因此,当禁用时,同一内核上的其他代码将无法干扰对数据结构的更新。自旋锁的重点是将“锁定”扩展到其他内核(尽管它是协作的,而不是硬件强制的)。

在不禁用中断的情况下在内核中使用自旋锁是危险/不负责任的,因为当发生中断时,当前代码将被挂起,现在您正在阻止其他内核在某些不相关的中断处理程序运行时取得进展(即使原始核心上的另一个用户进程或 tasklet 将无法抢占)。其他内核本身可能处于中断或 BH 上下文中,现在您正在延迟整个系统。自旋锁应该保持很短的时间来对共享数据结构进行关键更新。

这也是产生死锁的好方法。考虑上面的场景是否被复制到另一个子系统(或者可能是同一子系统中的另一个设备,但我将描述前者)。

在这里,核心 A 在子系统 1 中使用自旋锁而不禁用中断。同时,核心 B 在子系统 2 中采用自旋锁,也没有禁用中断。现在,如果与子系统 2 相关的中断发生在核心 A 上,并且在执行子系统 2 中断处理程序时,核心 A 需要更新由核心 B 中保存的自旋锁保护的结构。但大约在同一时间,子系统 1中断发生在核心 B 上,它需要更新该子系统中的数据结构。现在两个核心都在忙于等待另一个核心持有的自旋锁,并且整个系统都被冻结,直到您进行硬重置。

于 2018-10-08T15:55:49.517 回答