【并发控制讲解】

编译乱序

在赋值前使用编译屏障函数,来阻挡来自编译器优化产生的编译乱序问题

barrier();//在定义和赋值之间使用起到隔绝的作用

在Linux内核中,我们往往不喜欢volatile关键字,不仅仅是因为对解决编译乱序的问题作用较弱,而且也不具备保护临界资源的作用。(家人们,当我读到这的时候,终于想起c长考核的时候对我的代码嗤之以鼻了,毛病是真的多啊qwq)

执行乱序

上面的编译乱序是编译器产生的,那么执行乱序则是由于执行器导致的:老版本的ARM的确是会按顺序阻塞执行的,但是像ARM V6/V7或者新版本的处理器,是支持乱序处理的
举个例子CPU0执行:

while(f == 0);
print x;

CPU1执行:

x = 42;
f = 1;

咱们不能直接说CPU0上打印的x=42,因为两个处理器是处于并发状态,使用x不同的就是42。

因此Linux内核就存在了读写屏障mb(),读屏障rmb(),写屏障wmb(),寄存器读写__iormb()和__iowmb()这些屏障API。所以读写寄存器的API中readl_relaxed(),readl()和writel_relaxed(),writel()的区别就是有无屏障。
所以说在使用writel_relaxed()写完DMA的开始地址,结束地址,大小后,一定要调用writel()来启动DMA。

writel_relaxed(DMA_SRC_REG, src_addr);
writel_relaxed(DMA_DST_REG, dst_addr);
writel_relaxed(DMA_SIZE_REG, size);
writel(DMA_ENABLE, 1);

中断屏蔽

刚在学习的时候我就在想可不可以用中断来代替barrier(),不过这种想法并不在驱动开发中受到待见。but,CPU自己带有屏蔽中断和打开中断的功能,淦这种方法不仅是让中断和进程之间不再发生并发,内核抢占进程之间的并发也不会发生了。(看到它就意味着BUG来了)

中断屏蔽使用方法:
local_irq_disable()  //屏蔽中断
. . . 
critical section     //临界值 
. . .
local_irq_enable()   //开中断

原子操作

寄了,我当时第一次没搞明白原子操作是干啥的。我们可以理解成当我们的一个CPU在执行原子操作时,其他CPU禁止对内存或者非指向性的内存进行操作,所以可以避免竞态的产生。这个过程是可以被抢占,中断的,所以ARM指令中就增加了原子指令。分两类:位和整型变量。具体介绍等我更新。

自旋锁

其实自旋锁就是先执行一个原子操作,并设置一个内存变量,因为原子操作的特性,它执行自己的,不仅占别人的地,也无法去干扰。淦,还不明白就理解成一个变量,假设想要执行就需要进入X,X里面有自旋锁,A先进,同时A获得自旋锁,这个时候B也进入X,但自旋锁已经被A拿到了,所以要等A释放了自旋锁,B才能进入X。具体介绍等我更新(坑好像越挖越多了呀)。

读写自旋锁

顾名思义,读写用的,写操作只能有1个,读操作可以并发。等我更新qwq

信号量

和自旋锁的用法差不多,自旋锁是原地打转,信号量则是进入休眠等待状态(等待队列)。新版本的Linux内核都偏向直接使用mutex做为互斥手段,信号量就不再被推荐了。

未完待续

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值