Linux kernel Seq locks vs RCU vs Per CPU用例

Linux kernel Seq locks vs RCU vs Per CPU用例,linux-kernel,kernel,device-driver,Linux Kernel,Kernel,Device Driver,我试图了解一些内核同步机制(顺序锁vs RCU(读拷贝更新)vs每CPU锁)在编写设备驱动程序或内核模块时建议使用的不同用例。任何例子都将不胜感激。 读写器一致性机制,无需饥饿的写入器。这种 锁定读卡器需要一致信息集的数据 并愿意在信息更改时重试。有两种类型 读者: 从不阻止写入程序但可能必须重试的序列读取器 通过检测序列号的变化来确定写入程序是否正在进行。 写入程序不等待序列读取器 锁定读卡器,当写入程序或另一个锁定读卡器 正在进行中。正在进行的锁定读取器也会阻止写入程序 从未来开始。与常规的

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

读写器一致性机制,无需饥饿的写入器。这种 锁定读卡器需要一致信息集的数据 并愿意在信息更改时重试。有两种类型 读者:

  • 从不阻止写入程序但可能必须重试的序列读取器 通过检测序列号的变化来确定写入程序是否正在进行。 写入程序不等待序列读取器
  • 锁定读卡器,当写入程序或另一个锁定读卡器 正在进行中。正在进行的锁定读取器也会阻止写入程序 从未来开始。与常规的rwlock不同,这里的read锁是 独占,因此只有一个锁定读取器可以获得它
  • 这不像brlock那样对缓存友好。而且,这可能不起作用 对于包含指针的数据,因为任何编写器都可以 使读取器跟随的指针无效

    预期的非阻塞读卡器使用情况:

    do {
        seq = read_seqbegin(&foo);
        ...
    } while (read_seqretry(&foo, seq));
    
    在非SMP上,自旋锁消失,但写入程序仍需要 增加序列变量,因为中断例程可能 更改数据的状态


    RCU锁和每CPU锁在Rusty中进行了解释。

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

    #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()
    
    #包括
    类型定义结构{
    unsigned seq;=>每次写入程序获取锁时,seq都会递增
    自旋锁;
    }seqlock_t;
    写入\ seqlock(),写入\ sequnlock()
    read_seqlock(),read_sequnlock()
    
    注意:每次写入程序获取锁时,序列号都会递增,读卡器记录序列号的副本,然后执行读取,重新检查序列号(使用read_seqretry()),如果序列号不一致,则读卡器必须重新读取。对于有争议的读卡器,冗余读卡器并不比“旋转”CPU更糟糕,而对于无争议的读卡器,旋转锁可以一起避免

    RCU(读取副本更新)这将更新和回收信息分开,读卡器和写入器都可以避免完全锁定。RCU主要用于处理动态分配的数据结构,如链表。RCU编写器不会就地修改数据,而是分配一个新元素,并用更新的数据初始化该元素

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

    #include <linux/percpi.h>
    DEFINE_PER_CPU()
    per_cpu(var,cpu)
    get_cpu_var(), put_cpu_var()
    
    #包括
    定义每个CPU的容量()
    每个cpu(变量,cpu)
    get_cpu_var(),put_cpu_var()