>多cpu系统.
>所有cpu都使用通用(软件)资源.
>只读访问资源非常常见. (传入网络数据包的处理)
>写访问频率低得多. (仅限配置更改).
目前我使用read_lock_bh,write_lock_bh(自旋锁)机制.
问题是cpu越多,我在编写器上下文中获得的软锁定就越多.
我在this book阅读了并发章节,
但是在使用自旋锁时,无法理解读者或作者是否会获得优先权.
所以问题是:
> Linux自旋锁机制是否优先考虑读者/作者/没有?
>我可以使用更好的机制来避免在我的场景中出现那些软锁定,或者在使用我当前的解决方案时,可能是我在尝试获取锁定时优先考虑编写器的方法吗?
谢谢,
尼尔
解决方法
读者 – 作家锁
另一种专门的并发调节机制是自旋锁的读写器变体.如果使用一个
关键部分是这样的,即单独的线程可以读取或写入共享数据结构,但不能这样做
两者,这些锁都很自然.允许多个读取器线程同时在关键区域内.
Reader自旋锁的定义如下:
rwlock_t myrwlock = RW_LOCK_UNLOCKED; read_lock(&myrwlock); /* Acquire reader lock */ /* ... Critical Region ... */ read_unlock(&myrwlock); /* Release lock */
但是,如果编写器线程进入临界区,则不允许其他读取器或写入器线程进入.使用
写作者自旋锁,你会写这个:
rwlock_t myrwlock = RW_LOCK_UNLOCKED; write_lock(&myrwlock); /* Acquire writer lock */ /* ... Critical Region ... */ write_unlock(&myrwlock); /* Release lock */
查看net / ipx / ipx_route.c中的IPX路由代码,了解读写器自旋锁的实际示例.一个
名为ipx_routes_lock的读写器锁可以保护IPX路由表不被同时访问.主题
需要查找路由表以转发数据包请求读取器锁.需要添加或的线程
从路由表中删除条目获取编写器锁.这通常会提高性能
路由表查找的实例远多于路由表更新.
像常规自旋锁一样,读写器锁也有相应的irq变体 – 即read_lock_irqsave(),
read_lock_irqrestore(),write_lock_irqsave()和write_lock_irqrestore().这些语义
函数类似于常规自旋锁的函数.
2.6内核中引入的序列锁或序列锁是读写器锁,其中编写器受到青睐
读者.如果对远远超出读取的变量进行写操作,则此操作非常有用.一个例子是
本章前面讨论过的jiffies_64变量.作家线程不等待可能在里面的读者
一个关键部分.因此,读者线程可能会发现他们在关键部分内的输入失败了
并可能需要重试:
u64 get_jiffies_64(void) /* Defined in kernel/time.c */ { unsigned long seq; u64 ret; do { seq = read_seqbegin(&xtime_lock); ret = jiffies_64; } while (read_seqretry(&xtime_lock,seq)); return ret; }
编写器使用write_seqlock()和write_sequnlock()保护关键区域.
2.6内核引入了另一种称为读取副本更新(RCU)的机制,它产生了改进
当读者远远超过作家时的表现.基本思想是读者线程可以在没有的情况下执行
锁定.编写器线程更复杂.它们对数据结构的副本执行更新操作
替换读者看到的指针.保留原始副本,直到所有cpu上的下一个上下文切换为
确保完成所有正在进行的读取操作.请注意,使用RCU比使用RCU更复杂
到目前为止讨论的原语只有在你确定它是正确的工具时才应该使用. RCU数据
结构和接口函数在include / linux / rcupdate.h中定义.有充足的文档
文档/ RCU / *.
有关RCU用法示例,请查看fs / dcache.c.在Linux上,每个文件都与目录条目相关联信息(存储在称为dentry的结构中),元数据信息(存储在inode中)和实际数据(存储在数据块中).每次操作文件时,都会解析文件路径中的组件,并且获得相应的dentry. dentries保存在名为dcache,to的数据结构中加快未来的运营.在任何时候,dcache查找的数量远远超过dcache更新,因此使用RCU原语保护对dcache的引用.