成都网站建设qghl,亿网网络科技有限公司,东莞松山湖凯悦酒店,永康网站开发公司一、目的Linux驱动开发中有一个特别重要的知识点必须掌握#xff0c;即并发、竞态以及同步。什么是并发#xff1f;多个执行单元#xff08;进程、线程、中断#xff09;同时对一个共享资源的进行访问#xff1b;此处的共享资源可以是外设、内存或者软件层面的全局变量静态…一、目的Linux驱动开发中有一个特别重要的知识点必须掌握即并发、竞态以及同步。什么是并发多个执行单元进程、线程、中断同时对一个共享资源的进行访问此处的共享资源可以是外设、内存或者软件层面的全局变量静态变量等。什么是同步多个执行单元对同一个共享资源访问会引发竞态问题导致程序运行异常为了保证某个时刻只能有一个执行单元对共享资源进行操作就需要进行同步即独占访问即A在访问资源时B只能忙等待或或者休眠只有A释放其对共享资源的占用后B才能访问。情景分析上图中每条连线都代表并发可能发生的情景。进程可能由于其时间片段用完发生调度也有可能直接被更高优先级的进程抢占执行中断也可以打断进程的执行。在SMP多核系统中多个CPU都可以对外设或者内存进行访问所以并发的情景更加频繁。在单核支持抢占的系统中进程A的执行流程可能被进程B打断进程A的执行流程也可能被中断本身打断故在单核支持抢占的系统中并发也是现实存在的问题。针对并发问题Linux内核中提供了多种同步手段来协调资源的访问例如关中断单核简单系统中可用、原子操作、自旋锁、信号量、互斥锁、完成量等。但是我们细看其代码时我们会发现在ARM平台中原子操作或者其他同步机制都需要LDREX/STREX指令的参与还有更重要的一个知识点--屏障指令。本篇的目的就是帮助大家深入理解这两个指令的作用、实现原理以及应用。二、介绍参考资料https://developer.arm.com/documentation/dht0008/a/arm-synchronization-primitives/exclusive-accesses/ldrex-and-strex?langenLDREX/STREX是ARM架构上的同步原语属于硬件层面的同步机制。同步发生在当共享资源某个时刻只能被一个执行单元访问时共享资源可以是内存、外设设备执行单元可以是处理器、进程或者线程一般是通过以原子方式原子是最小的不可分割的修改代表资源状态的一个变量来实现同步修改操作只会有两个结果要么成功要么失败并且对所有的同时访问这个变量的执行单元都可见。在简单系统中可以通过开关中断的方式实现在多任务和多核系统中开关中断可能未必是个有效的方法频繁的开关中断会影响系统的实时处理和调度甚至有可能就是一个BUG所在。LDREX/STREX这两个指令配合独占监控器独占监控器会跟踪独占内存访问可以实现原子地更新内存数据。LDREX指令说明LDREX指令从内存中加载一个字word,并且初始化独占监控器的状态用来跟踪同步操作。LDREX R1, [R0]上面的代码片段从R0寄存器表示的地址中读取一个字存放在R1寄存器中并且更新独占监控器。STREX指令说明STREX指令将存储一个字到内存中但是这个存储指令是有条件的如果独占监控器允许这个存储操作那么对应的内存地址就会更新并且将返回值0保存在目标寄存器中代表此次操作成功如果独占监控器不允许那么就不会更新独占监控器并且将返回值1保存在目标寄存器中代表此次操作失败。基于上述逻辑我们就可以实现条件执行语句根据STREX不同的结果进行不同的操作。独占监控器在上面的描述中我们提到独占监控器独占监控器是一种简单的状态机其存在两种状态打开或者独占。为了实现多个处理器间的同步一般会存在两类独占监控器本地监控器和全局监控器。对非共享内存的独占访问只检查本地监控器对共享内存的独占访问会同时检查本地和全局监控器如果我们访问共享资源例如上图中的Memory B那么当CPU0访问B时CPU0的本地独占监控器会标记为已被独占同时全局独占监控器也会标记为已被独占全局监控器会监控多个CPU对共享资源的访问上图中Memory A只会被CPU0访问但是CPU0可能内部多个进程都会访问Memory A。独占监控器情景分析CPU0访问Memory A的情形时间进程1进程2T1LDREXT2...LDREXT3STREX...T4STREXT1时刻进程1调用LDREX此时本地监控器标记为已独占T2时刻进程2也调用LDREX此时也会标记本地监控器为已独占T3时刻进程1调用STREX此时由于本地监控器是独占状态所以进程1的STREX操作成功同时清除本地独占器的独占状态T4时刻进程2调用STREX但是此时本地独占器为Open状态故此处存储操作不成功所以进程2必须重新通过LDREX指令去获取内存值去判断。CPU0和CPU1访问Memory B的情形和上述基本类似此处不再赘述只要特别注意的是对于共享内存的访问会更新全局监控器STREX执行完毕后本地和全局独占监控器都会复位为Open状态。互斥锁实现基于LDREX/STREX这样的硬件特性我们可以实现互斥锁或者信号量注意lock_mutex/unlock_mutex函数中的DMB指令的使用实现信号量我们在实现互斥锁或者信号量时可以根据业务需要可以永久等待或者超时等待或者完全不等待仅查询是否可以获取到锁或者信号量。至此本篇的知识点就介绍完毕记得点赞收藏。