linux内核顺序锁,linux 顺序锁

linux 顺序锁

来源:华强电子网

作者:华仔

浏览:595

时间:2016-08-10 14:18

标签:

摘要:

当使用读/写自旋锁时,内核控制路径发出的执行read_lock或write_lock操作的请求具有相同的优先权:读者必须等待,直到写操作完成。同样地,写者也必须等待,直到读操作完成。Linux 2.6中引入了顺序锁(seqlock),它与读/写自旋锁非常相似,只是它为写者赋予了较高的优先级:事实上,即使在读者正在读的时候也允许写者继续运行。这种策略的好处是写者永远不会等待读(除非另外

当使用读/写自旋锁时,内核控制路径发出的执行read_lock或write_lock操作的请求具有相同的优先权:读者必须等待,直到写操作完成。同样地,写者也必须等待,直到读操作完成。

Linux 2.6中引入了顺序锁(seqlock),它与读/写自旋锁非常相似,只是它为写者赋予了较高的优先级:事实上,即使在读者正在读的时候也允许写者继续运行。这种策略的好处是写者永远不会等待读(除非另外一个写者正在写),缺点是有些时候读者不得不反复读多次相同的数据直到它获得有效的结果。

每个顺序锁都是包括两个字段的seqlock_t结构:

typedef struct {

unsigned sequence;

spinlock_t lock;

} seqlock_t;

一个类型为spinlock_t的lock字段和一个整型的sequence字段,第二个字段sequence是一个顺序计数器。

每个读者都必须在读数据前后两次读顺序计数器,并检查两次读到的值是否相同,如果不相同,说明新的写者已经开始写并增加了顺序计数器,因此暗示读者刚读到的数据是无效的。

通过把SEQLOCK_UNLOCKED赋给变量seqlock_t或执行seqlock_init宏,把seqlock_t变量初始化为“未上锁”,并把sequence设为0:

http://blog。21ic。com/user1/1729/archives/2012//#define __SEQLOCK_UNLOCKED(lockname) /

{ 0, __SPIN_LOCK_UNLOCKED(lockname) }

http://blog。21ic。com/user1/1729/archives/2012//#define SEQLOCK_UNLOCKED /

__SEQLOCK_UNLOCKED(old_style_seqlock_init)

http://blog。21ic。com/user1/1729/archives/2012//# define __SPIN_LOCK_UNLOCKED(lockname) /

(spinlock_t)    {    .raw_lock = __RAW_SPIN_LOCK_UNLOCKED,    /

SPIN_DEP_MAP_INIT(lockname) }

http://blog。21ic。com/user1/1729/archives/2012//#define __RAW_SPIN_LOCK_UNLOCKED    { 1 }

写者通过调用write_seqlock()和write_sequnlock()获取和释放顺序锁。write_seqlock()函数获取seqlock_t数据结构中的自旋锁,然后使顺序计数器sequence加1;write_sequnlock()函数再次增加顺序计数器sequence,然后释放自旋锁。这样可以保证写者在整个写的过程中,计数器sequence的值是奇数,并且当没有写者在改变数据的时候,计数器的值是偶数。读者进程执行下面的临界区代码:

unsigned int seq;

do {

seq = read_seqbegin(&seqlock);

/* ... CRITICAL REGION ... */

} while (read_seqretry(&seqlock, seq));

read_seqbegin()返回顺序锁的当前顺序号;如果局部变量seq的值是奇数(写者在read_seqbegin()函数被调用后,正更新数据结构),或seq的值与顺序锁的顺序计数器的当前值不匹配(当读者正执行临界区代码时,写者开始工作),read_seqretry()就返回1:

static __always_inline int read_seqretry(const seqlock_t *sl, unsigned iv)

{

smp_rmb();

return (iv & 1) | (sl->sequence ^ iv);

}

注意在顺序锁机制里,读者可能反复读多次相同的数据直到它获得有效的结果(read_seqretry返回0)。另外,当读者进入临界区时,不必禁用内核抢占;另一方面,由写者获取自旋锁,所以它进入临界区时自动禁用内核抢占。

并不是每一种资源都可以使用顺序锁来保护。一般来说,必须在满足下述条件时才能使用顺序锁:

(1)被保护的数据结构不包括被写者修改和被读者间接引用的指针(否则,写者可能在读者的眼皮子底下就修改指针)。

(2)读者的临界区代码没有副作用(否则,多个读者的操作会与单独的读操作有不同的结果)。

此外,读者的临界区代码应该简短,而且写者应该不常获取顺序锁,否则,反复的读访问会引起严重的开销。在Linux 2.6中,使用顺序锁主要是保护一些与系统时间处理相关的数据结构。

技术资讯 技术方案 技术应用 技术新品 技术前沿 行业资讯 行业方案 行业应用 行业新品 行业前沿

分享到:

eb16ac850798d72e084e2c3ed33ff707.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值