当前位置: 首页 > news >正文

南京公司网站模板建站都江堰做网站

南京公司网站模板建站,都江堰做网站,网站收款接口,九江建设监督网站Linux 内核有非常多的锁机制,如:自旋锁、读写锁、信号量和 RCU 锁等。本文介绍一种和读写锁比较相似的锁机制:顺序锁(seqlock)。 顺序锁与读写锁一样,都是针对多读少写且快速处理的锁机制。而顺序锁和读写…

Linux 内核有非常多的锁机制,如:自旋锁、读写锁、信号量和 RCU 锁等。本文介绍一种和读写锁比较相似的锁机制:顺序锁(seqlock)。

顺序锁与读写锁一样,都是针对多读少写且快速处理的锁机制。而顺序锁和读写锁的区别就在于:读写锁的读锁会阻塞写锁,而顺序锁的读锁不会阻塞写锁。

读锁原理

为了让读锁不阻塞写锁,读锁并不会真正进行上锁操作。那么读锁是如何避免在读取临界区数据时,数据被其他进程修改了?

为了解决这个问题,顺序锁使用了一种类似于版本号的机制:序号。序号是一个只增不减的计数器,可以从顺序锁对象的定义看出,如下代码所示:

typedef struct {struct seqcount seqcount; // 序号spinlock_t lock;          // 自旋锁,写锁上锁时使用
} seqlock_t;

在读取临界区数据前,首先需要调用 read_seqbegin() 函数来获取读锁,read_seqbegin() 函数的核心逻辑是读取顺序锁的序号。代码如下所示:

static inline unsigned read_seqbegin(const seqlock_t *sl)
{unsigned ret;repeat:// 读取顺序锁的序号ret = sl->sequence;// 如果序号是单数,需要重新获取if (unlikely(ret & 1)) {...goto repeat;}...return ret;
}

从上面的代码可以看出,read_seqbegin() 函数只获取顺序锁的序号,并不会进行上锁操作,所以读锁并不会阻塞写锁。

注意:序号是单数时需要重新获取的原因,会在分析写锁实现原理时说明。

既然读锁并不会进行上锁操作,如果在读取临界区数据时,数据被修改了怎么办呢?答案就是:在退出临界区时,比较一下当前顺序锁的序号跟之前读取的序号是否一致。如果一致表示数据没有被修改,否则说明数据已经被修改。如果数据被修改了,那么需要重新读取临界区的数据。

比较序号是否一致可以使用 read_seqretry() 函数,所以读锁的正确用法如下代码所示:

do {// 获取顺序锁序号unsigned seq = read_seqbegin(&seqlock);// 读取临界区数据...
} while (read_seqretry(&seqlock, seq)); // 对比序号是否一致?

read_seqretry() 函数的实现非常简单,如下所示:

static inline unsigned 
read_seqretry(const seqlock_t *sl, unsigned start)
{...return sl->sequence != start;
}

从上面代码可以看出,read_seqretry() 函数只是简单比较当前序号与之前读取到的序号是否一致。

写锁原理

从上面的分析可知,读锁是通过对比前后序号是否一致来判断数据是否被修改的。那么序号在什么时候被修改呢?答案就是:获取写锁时。

获取写锁是通过 write_seqlock() 函数来实现的,其实现也比较简单,代码如下所示:

static inline void write_seqlock(seqlock_t *sl)
{spin_lock(&sl->lock);sl->sequence++;...
}

write_seqlock() 函数首先会获取自旋锁(所以写锁与写锁之间是互斥的),然后对序号进行加一操作。所以,在修改临界区数据前,写锁先会增加序号的值,这样就会导致读锁前后两次获取的序号不一致。我们可以用下图来说明这种情况:

seqlock原理

 资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈

可以看出,当在读临界区前后获取的序号值不一致时,就表示数据已经被修改,这时就需要重新读取被修改后的数据。

写锁解锁也很简单,代码如下:

static inline void write_sequnlock(seqlock_t *sl)
{...s->sequence++;spin_unlock(&sl->lock);
}

解锁也需要对序号进行加一操作,然后释放自旋锁。

由于 write_seqlock() 函数与 write_sequnlock() 函数都会对序号进行加一操作,所以解锁后,序号的值必定为双数。

我们在分析读锁时看到,如果序号是单数时会重新获取序号,直到序号为双数为止。这是因为序号单数时,表示正在更新数据。此时读取临界区的值是没有意义的,所以需要等到更新完毕再读取。

原文作者:Linux内核那些事

http://www.yayakq.cn/news/206264/

相关文章:

  • 网站版权模板兰州seo推广
  • 手机网站域名m.做移动网站优
  • 公司网站策划上海的广告公司有哪些
  • 遂宁商城网站建设报价网站的基本结构
  • 中盛腾龙建设工程有限公司网站电子商务网站建设a卷
  • 宁波网站建设 网络服务用什么建设网站
  • 毕设做网站怎么弄代码设计网页设计师用什么软件
  • mstsc做网站silverlight 做的网站
  • 做网站是如果盈利的网站建设教程学习
  • 国内做受网站怎么建公众号申请
  • 邢台做网站的公司哪家好?装饰公司网站开发
  • 提供手机网站开发企业信息公示管理系统
  • 网站开发和游戏开发哪个难网站建设 xplogo
  • 上城网站建设远涛网站建设
  • 网站目录访问北京网站建设定制型报价
  • 好的做问卷调查的网站好建筑人工作网
  • 企业免费网站建设哪里比较好网页制作教程简明
  • 织梦大气婚纱影楼网站源码今天的湖北新闻
  • 重庆模板做网站做便民网站都需要哪些模块
  • 如何做旅游网站的旅行家网站后台字体安装
  • 网站活动策划方案房产网签是什么意思 网签的意义是什么
  • 企业网站建设有哪些什么是百度权重
  • 深圳东门步行街在哪个区seo关键词布局案例
  • 一学一做教育视频网站有哪些全定制网站开发
  • dede网站logo怎么改天津市城乡建设网
  • 网站建设大题建立平台要多少钱
  • 网站制作应该注意到的问题logo模板
  • 猎头自己在哪个网站做单做aelogo动效有什么好的网站
  • 全景网站如何做深圳seo招聘
  • 站长seo计费系统青岛公司网站建设公司