`
tempsitegoogle
  • 浏览: 866984 次
文章分类
社区版块
存档分类
最新评论

顺序锁

 
阅读更多

顺序锁


当使用读/写自旋锁时,内核控制路径发出的执行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:
#define __SEQLOCK_UNLOCKED(lockname) /
{ 0, __SPIN_LOCK_UNLOCKED(lockname) }

#define SEQLOCK_UNLOCKED /
__SEQLOCK_UNLOCKED(old_style_seqlock_init)

# define __SPIN_LOCK_UNLOCKED(lockname) /
(spinlock_t) { .raw_lock = __RAW_SPIN_LOCK_UNLOCKED, /
SPIN_DEP_MAP_INIT(lockname) }
#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中,使用顺序锁主要是保护一些与系统时间处理相关的数据结构。


当使用读/写自旋锁时,内核控制路径发出的执行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:
#define __SEQLOCK_UNLOCKED(lockname) /
{ 0, __SPIN_LOCK_UNLOCKED(lockname) }

#define SEQLOCK_UNLOCKED /
__SEQLOCK_UNLOCKED(old_style_seqlock_init)

# define __SPIN_LOCK_UNLOCKED(lockname) /
(spinlock_t) { .raw_lock = __RAW_SPIN_LOCK_UNLOCKED, /
SPIN_DEP_MAP_INIT(lockname) }
#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中,使用顺序锁主要是保护一些与系统时间处理相关的数据结构。

分享到:
评论

相关推荐

    基于STM8S903K3的序列打螺丝夹具的硬件设计与实现

    本文以STM8S903K3为主控芯片,设计了一款按照统一顺序锁紧螺丝的装置——序列打螺丝夹具,文章首先提出了设计方案,然后给出了序列打螺丝夹具的原理框图并针对芯片外围电路模块进行了重点设计说明,最后对运行状态...

    疯狂内核之——进程管理子系统

    4.7 顺序锁 215 4.8 RCU机制 217 4.9 信号量 219 4.9.1 获取和释放信号量 221 4.9.2 读/写信号量 224 4.9.3 补充信号量 225 4.10 禁止本地中断 226 4.10.1 禁止本地中断 227 4.10.2 禁止下半部(可延迟函数) 229 ...

    UML的顺序图

    UML 的 顺序图详解!

    电子密码锁555单稳态电路设计攻略

    电路密码只有16 种可供修改,但由于他人不知道密码的位数,而且还要求在规定的时间内按一定的顺序开锁,所以他人开锁的几率很小。下面介绍让人感到更安全、更方便、更放心的新型电子密码锁基于555 单稳态电路的设计...

    基于zookeeper临时顺序节点实现分布式调度

    利用zookeeper的临时顺序节点实现分布式锁,同时控制多个quartz示例协作执行的代码。

    罗克韦尔自动化-基于控制器的可扩展批次和顺序控制解决方案概述.pdf

    罗克韦尔自动化-基于控制器的可扩展批次和顺序控制解决方案概述pdf,

    多核编程入门

    3.1.3 总线锁-原子操作原语 ............................................................................................................ 12 3.2 缓存一致性 ..................................................

    ET199写锁文件,部分广联达2018授权过期,亲测可用使用,但无写锁工具,可使用旧版写锁工具。

    给部分无法使用或过期的授权用户,本着我为人人,人人为我,使用时多安装几次,顺序为写锁,重启,授权,重启,注意查看广联达新驱动中:我的授权,

    Linux内核同步机制

    Linux内核同步机制,挺复杂的一个东西,常用的有自旋锁,信号量,互斥体,原子操作,顺序锁,RCU,内存屏障等。这里说说它们的特点和基本用法。  自旋锁 :通用的 和读写的  特点:  1. 处理的时间很短。  2...

    Android九宫格解锁

    基于Android的九宫格解锁,屏蔽手机Home键和返回键,置于系统锁屏之前,适合初学者,利用Android Studio进行开发的源码,代码简单,注释详细

    论文研究-面向多核环境的BDD工具设计与优化 .pdf

    面向多核环境的BDD工具设计与优化,施佳鑫,陈榕,针对传统二分决策图(BDD)可扩展性(Scalability)问题,提出了一种面向多核处理器的并行BDD库的方法,利用顺序锁(seqlock)以及原子性比较��

    三相电机顺序启动控制电路图

    三相电动机控制电路实现顺序控制电路图解 下图(a)所示为三相电动机控制电路实现顺序控制电路的线路图。此控制线路的特点是:电动机M2的控制电路先与接触器KM1的线圈并接后再与KM1的自锁触头串接,这样就保证了...

    三个线程使用条件变量的notify和锁按顺序输出数字

    使用条件变量控制三个线程按顺序输出数字, 第一个线程输出3的倍数余1, 第二个线程输出3的倍数余2, 第三个线程输出3的倍数

    线程顺序输出的问题

    这个小程序写了三个线程是按照我的意愿来输出的,其中要利用lock锁与condition_t2.signal();

    锁链 非递归做法C++.zip

    为了挽回,于是国王决定用Bytish锁链将其锁在墙上。这种锁链由n(10≤n≤1000)个固定在墙上的铁环和铁棒组成。由于环不是都套在棒上,要想把整副锁链取下是十分困难的。数学家必须自己通过不断取下和套上铁环最终将...

    JosephusGame:一个简单的游戏,灵感来自约瑟夫斯问题

    约瑟夫斯游戏 受约瑟夫斯问题启发的简单游戏....................................................... 这个应用程序使用的是带有随机值的蛋,而不是人,所有蛋都可以连续顺序解锁,但每个玩家都可以解锁。 鸡蛋上的值

    密码锁的设计与实现 课程设计 数字逻辑与数字系统

    这次是密码锁的设计与实现,里面什么都全,有图片,有程序。

    gpp 3to2 解锁工具

    由于iTunes中涉及到多个相互依存的组件,因此请按照以下顺序,在"控制面板"->"添加或删除程序"中卸载iTunes和相关组件: 1)、iTunes 2)、Apple Software Update 3)、Bonjour 4)、Apple Mobile Device Support...

    带自锁功能的简易密码锁

    带自锁功能的简易密码锁2003年,第7期,类别:电子制作 本密码锁的特点是,如果按错了密码键顺序或按下了任何一个非密码键,电路即锁定为关断状态,各按键均失效,大大增加了开锁难度。 电路见图。可控硅SCR5、...

    59.Lock-ReentranLock-实现线程的顺序执行.mp4

    在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。

Global site tag (gtag.js) - Google Analytics