在RCU读端临界区使用list_for_each_entry()会引发问题吗?
RCU链表遍历替换的风险分析
先明确两个遍历宏的本质区别:
list_for_each_entry_rcu()是为RCU读端临界区量身设计的,它会配合RCU机制,保证遍历过程中即使有写线程修改链表,读线程也能安全访问节点内存——RCU会延迟释放被删除的节点,直到所有读临界区完成。list_for_each_entry()是普通链表遍历宏,没有任何RCU相关的内存屏障、访问保证,完全不考虑并发修改场景。
如果在RCU读临界区里用list_for_each_entry()替换list_for_each_entry_rcu(),会直接引发以下问题:
- 野指针与内核崩溃:当写线程删除某个节点并立即释放内存时,普通遍历宏不会感知RCU的延迟释放规则,读线程遍历到该节点时会访问已被释放的内存,触发野指针引用,直接导致内核崩溃、数据损坏,或者出现完全不可预知的系统行为。
- 链表遍历异常:如果写线程在遍历过程中修改链表的
next/prev指针(比如移动节点),普通遍历宏没有内存屏障来保证链表结构的一致性,读线程可能看到断裂或循环的链表结构,出现遍历死循环、跳过节点、重复访问节点等异常。 - 破坏RCU语义:RCU的核心是读无锁,写线程修改时无需阻塞读线程,但普通遍历宏不配合RCU读临界区的语义,会打破RCU的内存可见性规则,读线程可能无法看到写线程的修改,或者看到修改的中间状态,导致遍历结果完全错误。
注意:如果系统中没有并发写操作,单纯用普通遍历宏可能暂时不出问题,但只要存在并发写,上述风险必然触发——普通遍历宏完全不具备RCU保护链表的遍历安全能力。
内容的提问来源于stack exchange,提问作者hdthky
相关产品推荐
相关产品推荐

