这几天,我正在研究内核内部网络代码,尤其是 RPS 代码。您知道,有很多功能。但是我主要关注一些有关 SMP队列处理的功能,例如enqueue_to_backlog
和process_backlog
。
我想知道通过使用两个功能-enqueue_to_backlog
和process_backlog
-来同步两个内核(或单个内核)。
在该功能中,一个核心(A)拥有另一个核心(B)的spin_lock
,用于将数据包排队到input_pkt_queue
中并调度核心(B)的napi 。而且核心(B)还拥有spin_lock
,用于将input_pkt_queue
拼接到核心(B)的process_queue
上,并自行删除napi计划。 spin_lock
应该被保留,以防止两个内核在处理队列期间彼此访问同一队列。
但是我不明白为什么用 我认为不可能通过其他BH(例如tasklet)抢占当前上下文(napi,softirq)。是真的吗并且我想知道local_irq_disable是禁用所有内核irq还是仅禁用当前内核的irq?实际上,我读了一本有关内核开发的书,但是我认为我对理解先发知识还不够。 将解释rps过程将spin_lock
(或local_irq_disable
)调用local_irq_save
。我认为,当中断(TH)抢占当前上下文(softirq,BH)时,就无法通过中断上下文(TH)访问核心(B)的队列或rps_lock
。-当然, TH可以访问napi结构来调度napi,但是它一直保持禁用irq,直到对数据包进行排队-所以我想知道为什么spin_lock
是通过irq disable调用的。
spin_lock
与local_irq_disable
一起使用的原因吗?
答案 0 :(得分:0)
禁用中断会影响当前内核(仅)。因此,如果禁用,则同一内核上的其他代码 将无法干扰数据结构的更新。自旋锁的目的是将“锁定”扩展到其他内核(尽管它是协作的,而不是硬件强制的)。
在内核中 禁用自旋锁是危险/不负责任的,因为禁用中断是因为当发生中断时,当前代码将被挂起,现在您正在阻止其他内核取得进展当某些不相关中断处理程序正在运行时(即使原始内核上的另一个用户进程或tasklet无法抢占)。其他内核本身可能处于中断或BH上下文中,现在您正在延迟整个系统。自旋锁应该保留很短的时间,以便对共享数据结构进行重要更新。
这也是生成死锁的好方法。考虑是否将上述方案复制到另一个子系统(或可能在同一子系统中的另一个设备,但是我将描述前者)。
在这里,内核A在子系统1中获得了自旋锁,而没有禁用中断。同时,内核B在子系统2中也处于自旋锁状态,而不禁用中断。现在,如果在内核A上发生与子系统2有关的中断,并且在执行子系统2中断处理程序时,内核A需要更新受内核B中保存的自旋锁保护的结构,那么会发生什么。但是大约在同一时间,子系统1中断发生在核心B上,核心B需要更新该子系统中的数据结构。现在,两个内核都在忙于等待另一个内核持有的自旋锁,并且整个系统都将冻结,直到您执行硬重置为止。