Linux内核锁的那点事 微速讯
来源:嵌入式艺术 发布时间:2023-07-04 14:38:55

Linux设备驱动中,我们必须要解决的一个问题是:多个进程对共享资源的并发访问,并发的访问会导致竞态。

1、并发和竞态

并发(Concurrency):指的是多个执行单元同时、并行的被执行。


【资料图】

竞态(RaceConditions):并发执行的单元对共享资源的访问,容易导致竞态。

共享资源:硬件资源和软件上的全局变量、静态变量等。

解决竞态的途径是:保证对共享资源的互斥访问。

互斥访问:一个执行单元在访问共享资源的时候,其他执行单元被禁止访问。

临界区(Critical Sections):访问共享资源的代码区域成为临界区。临界区需要以某种互斥机制加以保护。

常见的互斥机制包括:中断屏蔽,原子操作,自旋锁,信号量,互斥体等。

2、竞态发生的场合

image-20230511140139520

多对称处理器(SMP)的多个CPU之间

多个CPU使用共同的系统总线,可以访问共同的外设和存储器。在SMP的情况下,多核(CPU0、CPU1)的竞态可能发生于:

CPU0的进程和CPU1的进程之间CPU0的进程和CPU1的中断之间CPU0的中断和CPU1的中断之间单CPU内,该进程与抢占它的进程之间

在单CPU内,多个进程并发执行,当一个进程执行的时间片耗尽,也有可能被另一个高优先级进程打断,会发生竞态。

中断(软中断、硬中断、Tasklet、底半部)与进程之间

当一个进程正在执行,一个外部/内部中断(软中断、硬中断、Tasklet等)将其打断,会导致竞态发生。

3、编译乱序和执行乱序

除了并发访问导致的竞态外,还需要了解编译器和处理器的一些特点所引发的一些问题。

3.1 编译乱序

现代的高性能编译器在目标代码优化上都具有乱序优化的能力,编译器为了尽量 提高Cache命中率以及CPU的Load/Store单元的工作效率,可以对访存的指令进行乱序,减少逻辑上不必要的访存。

因此,在打开编译器优化后,生成的汇编码并没有严格按照代码的逻辑顺序执行,这是正常的。

为了解决编译乱序的问题,可以加入barrier()编译屏障

该屏障可以阻挡编译器的优化。设置屏障的前后,可以保证执行的语句不乱。

加入barrier()编译屏障,即可保证正确的执行顺序。

例子:

#define barrier() __asm__ __volatile__("": : :"memory")int main(int argc,char *argv[]){ int a = 0,b,c,d[4096],e; e = d[4095];    barrier(); b = a; c = a; return 0;}

3.2 执行乱序

编译乱序是编译器的行为,而执行乱序就是处理器运行时的行为。

高级的CPU往往会根据自身的缓存特性,将访存指令重新排序执行!这样就导致了多个顺序的指令,后发的指令仍有可能先执行完毕。

这种执行乱序,在多个CPU之间,以及单个CPU内部,都是非常常见的。

3.2.1 多CPU之间

处理器为了解决多核之间,一个CPU的行为对另一个CPU可见的情况,ARM处理器引入了内存屏障指令:

DMB(数据内存屏障),保证在该指令前的所有指令,内存访问完成,再去访问该指令之后的访存动作DSB(数据同步屏障),保证在该指令前的所有访存指令执行完毕(访存,缓存,跳转预测,TLB维护等)完成ISB(指令同步屏障),Flush流水线,保证所有在ISB之后执行的指令都是从缓存或者内存中获得。

3.2.2 单CPU内部

在单CPU中,我们常遇到访问外设寄存器时,某些外设寄存器就对读写顺序有很高的要求,为了避免执行乱序的发生,这时候就需要CPU的一些内存屏障指令了。

CPU内部,为了解决这种问题,CPU提供了一些内存屏障指令:

可以参考Documentation/memory-devices.txtDocumentation/io_ordering.txt

读写屏障:mb()读屏障:rmb()写屏障:wmb()寄存器读屏障__iormb()__寄存器写屏障__iowmb()__
#define writeb_relaxed(v,c) __raw_writeb(v,c)#define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c)#define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c)#define readb(c)  ({ u8  __v = readb_relaxed(c); __iormb(); __v; })#define readw(c)  ({ u16 __v = readw_relaxed(c); __iormb(); __v; })#define readl(c)  ({ u32 __v = readl_relaxed(c); __iormb(); __v; })#define writeb(v,c)  ({ __iowmb(); writeb_relaxed(v,c); })#define writew(v,c)  ({ __iowmb(); writew_relaxed(v,c); })#define writel(v,c)  ({ __iowmb(); writel_relaxed(v,c); })

writelwritel_relaxed的区别就在于有无屏障。

4、总结

由上文可知,为了解决

并发导致的竞态问题高性能的编译器编译乱序问题高性能的CPU带来的执行乱序问题

CPUARM处理器提供的内存屏障指令等,这也是内核锁存在的意义。

标签:

猜你喜欢

Linux内核锁的那点事 微速讯

Linux内核锁的那点事-在Linux设备驱动中,我们必须要解决的一个问题是更多

2023-07-04 14:38:55

金字旁加土好吗_金字旁加土 环球报资讯

1、锉,拼音:cuò。2、锉尸锉刀锉子扁锉土锉斫锉捣锉顿锉锉荐板锉摧锉更多

2023-07-04 14:09:28

灵耀x2pro美行售价(灵耀x2pro)|天天即时

来为大家解答以上问题,灵耀x2pro美行售价,灵耀x2pro很多人还不知道,更多

2023-07-04 13:15:21

环球快消息!《逆水寒手游》天动星回探索攻略详解

逆水寒手游是一款武侠风格的角色扮演游戏,通过参与剧情任务和挑战,你更多

2023-07-04 12:40:46

新车到手应该做什么检查(新车到手应该做什么)

想必现在有很多小伙伴对于新车到手应该做什么方面的知识都比较想要了解更多

2023-07-04 12:09:25

南川:踔厉奋发,高三启航

7月3日,重庆市南川中学校举行高2024届走进高三启航仪式。高三启航仪式更多

2023-07-04 11:37:16

win7关闭22端口的方法

1 首先了解22端口是用来干什么的。22端口是SSH协议的默认端口,用来进更多

2023-07-04 11:08:17

【环球快播报】连跌一年半后 笔记本电脑触底反弹

连跌一年半后笔记本电脑触底反弹了:AMD、Intel松了一口气更多

2023-07-04 11:12:12

这部爽片续作翻车了

这部爽片续作翻车了,魔女,片末,打戏,文戏,续作,翻车,毒舌律师更多

2023-07-04 10:21:27

真相大白!“徐楚平杀妻疑案”判决18年后 两真凶

真相大白!“徐楚平杀妻疑案”判决18年后两真凶落网更多

2023-07-04 10:06:46