Seq-locks vs RCU vs Per-CPU用例

时间:2014-11-05 16:14:57

标签: linux-kernel kernel device-driver

我试图了解一些内核同步机制的不同用例(顺序锁与RCU(读取 - 复制 - 更新)与每CPU锁)建议用于编写设备驱动程序或内核模块。任何例子都将不胜感激。

2 个答案:

答案 0 :(得分:6)

顺序锁这是一种聪明的锁定方法,其中编写者获得自旋锁,读者可以完全避免锁定,代价是不得不重复不一致的读取。这种方法最适用于经常读取数据但很少更新的情况。 这里多次读取不会产生副作用,这与任何读写器锁定和更新类似,不会同时混淆读者。搜索使用/包含API / headers / data结构的内核代码:

#include <linux/seqlock.h>
typedef struct {
    unsigned seq;  ===> seq is incremented every-time a writer acquires a lock
    spinlock_t lock;
} seqlock_t;
write_seqlock(), write_sequnlock()
read_seqlock(), read_sequnlock()

注意:每次编写器获取锁定时,seq no都会递增,读取器,记录seq编号的副本,然后执行读取,重新检查序列号(使用read_seqretry()),如果seq编号是不一致,那么读者必须重新阅读。对于有争议的读者来说,冗余读取并不比“旋转”CPU更糟糕,对于无争议的读者来说,可以一起避免自旋锁。

RCU(读取 - 复制 - 更新)这将更新和回收信息分开,读者和编写者都可以完全避免锁定。 RCU主要用于处理动态分配的数据结构,例如链表。 RCU编写器不会修改数据,而是分配一个新元素,它使用更新的数据进行初始化。

PER-CPU变量这些主要用于CPU特定结构,可以避免全局锁定。请注意,这些仍必须与ISR同步。类似地:

#include <linux/percpi.h>
DEFINE_PER_CPU()
per_cpu(var,cpu)
get_cpu_var(), put_cpu_var()

答案 1 :(得分:2)

seqlock documentation说:

  

读者/作者一致的机制,没有饥饿的作家。这类   锁定数据,读者需要一组一致的信息   并且如果信息发生变化,愿意重试。有两种类型   读者:

     
      
  1. 从不阻止作者的序列阅读器,但他们可能需要重试   如果作者正在通过检测序列号的变化而进行。   作家不等待序列阅读器。
  2.   
  3. 锁定读者,如果是作家或其他锁定阅读器,则会等待   正在处理。正在进行的锁定阅读器也会阻止作者   从前进。与常规的rwlock不同,这里的读锁定是   独家,这样只有一个锁定阅读器才能获得它。
  4.         

    这不像brlock那样缓存友好。此外,这可能不会很好   对于包含指针的数据,因为任何编写者都可以   使读者关注的指针无效。

         

    预期的非阻止读者使用:

    do {
        seq = read_seqbegin(&foo);
        ...
    } while (read_seqretry(&foo, seq));
    
         

    在非SMP上,自旋锁消失但作者仍然需要   增加序列变量,因为中断例程可以   改变数据的状态。

在Rusty的Unreliable Guide To Locking中解释了RCU和每CPU锁定。