六、Linux的同步与互斥机制

一、内联汇编

为什么使用内联汇编

  • 为了更高效的操作。C语言中调用函数都会设计到各种入栈和出栈的操作,哪怕只是一个非常简单的函数。对于这样的函数,如果需要经常调用的话,写成汇编会提高代码的执行效率。
  • 为了使用一些C语言不支持的汇编指令,比如 ldrex / strex 。

C语言内联汇编代码

  • __asm__表示这是一段内联汇编代码
  • 输出操作数 “=r” 表示这是一个early clobber(早早修改好了),编译器不能为了省事,自作聪明地对其进行优化,将其与输入共用寄存器。

二、原子操作

对于小于ARMv6架构的处理器,因为不支持SMP,所以Linux实现原子操作的方法是直接关中断。

对于大于等于ARMv6架构的处理器,Linux实现原子操作的方法是使用 LDREX / STREX 同步原语。注意 LDREX / STREX 要成对使用,LDREX加载数据并且标记访问地址为独占,STREX会判断独占标记,并根据标记进行操作,具体如下:

  • 独占标记仍在时(表明操作未被抢占),写入新值,清除独占标记,RET = 0
  • 独占标记不在了(表明操作被其它 LDREX /STREX 抢占了),则放弃写入,RET = 1

原子操作的原理就是,利用 LDREX / STREX 实现一个完整的“读-修改-写”的过程。如果写回的时候发现被抢占,则应重复“读-修改-写”的过程,直到操作成功为止(STREX的返回值为0)。Linux中的同步和互斥机制,都是基于原子操作来实现的。

三、Linux中的锁

Linux中的锁分为两类:自旋锁和休眠锁

自旋锁一开始是面向多CPU系统的,获取不到锁就原地打转,会占用CPU资源,所以自旋锁适合用在短暂等待的情况,比如别人可能很快就会释放锁的情况。对于自旋锁,根据CPU的情况,实现会不同:

  • 多CPU时,使用原子变量实现
  • 单CPU时,直接禁止调度,所以spin_lock退化成了preempt_disable(对于比较老的内核,由于本来就不支持抢占,所以spin_lock可以是一个空函数)。

休眠锁跟自旋锁不同,得不到的话就会休眠,不占用CPU资源。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值