一. 简介
 Linux是一个多任务操作系统,肯定会存在多个任务共同操作同一段内存或者设备的情况, 多个任务甚至中断都能访问的资源叫做共享资源,在驱动开发中要注意对共享资源的保护,也就是要处理对共享资源的并发访问。比如,共享单车,大家按照谁扫谁骑走的原则来共用这个单车,如果没有这个并发访问共享单车的原则存在,只怕到时候为了一辆单车要打起来了。 
 
 在 Linux 驱动编写过程中,对于并发控制的管理非常重要。 
 
 
 本文简单了解一下Linux中并发与竞争的概念。 
 
 
 
 
二. Linux并发与竞争的基本概念
1. 并发与竞争简介
 并发就是多个 “用户” 同时访问同一个共享资源,比如,你们公司有一台打印机,你们公司的所有人都可以使用。现在小李和小王要同时使用这一台打印机,都要打印一份文件。小李要 打印的文件内容如下: 
 
我叫小李
电话:123456
工号:16 小王要打印的内容如下:  
 
我叫小王
电话:678910
工号:20 这两份文档肯定是各自打印出来的,不能相互影响。当两个人同时打印的话如果打印机不做处理的话可能会出现小李的文档打印了一行,然后开始打印小王的文档,这样打印出来的文档就错乱 了,可能会出现如下的错误文档内容:  
 
我叫小王
电话:123456
工号:20可以看出,小王打印出来的文档中电话号码错误了,变成小李的了,这是绝对不允许的。如果有多人同时向打印机发送了多份文档,打印机必须保证一次只能打印一份文档,只有打印完成以后才能打印其他的文档。
2. 并发产生的原因
 Linux  系统是个多任务操作系统,会存在多个任务同时访问同一片内存区域,这些任务可 能会相互覆盖这段内存中的数据,造成内存数据混乱。针对这个问题必须要做处理,严重的话  可能会导致系统崩溃。现在的  Linux  系统并发产生的原因很复杂,总结一下有下面几个主要原 因:  
 
 ①  多线程并发访问, Linux  是多任务 ( 线程 ) 的系统,所以多线程访问是最基本的原因。  
 
 ②  抢占式并发访问,从  2.6  版本内核开始, Linux  内核支持抢占,也就是说调度程序可以 在任意时刻抢占正在运行的线程,从而运行其他的线程。  
 
 ③  中断程序并发访问,这个无需多说,学过  STM32  的同学应该知道,硬件中断的权利可 是很大的。  
 
 ④  SMP( 多核 ) 核间并发访问,现在  ARM  架构的多核  SOC  很常见,多核  CPU  存在核间并 发访问。  
 
 
 并发访问带来的问题就是竞争,学过 FreeRTOS 和 UCOS 的同学应该知道临界区这个概念,所谓的临界区就是共享数据段,对于临界区必须保证一次只有一个线程访问,也就是要保证临  界区是原子访问的,这里的原子访问就表示这一个访问是一个步骤,不能再进行拆分。 如 果多个线程同时操作临界区就表示存在竞争。 
 
 我们在编写驱动的时候,一定要注意避免并发和防止竞争访问。 很多  Linux 驱动初学者往往不注意这一点,在驱动程序中埋下了隐患,这类问题往往又很不容易查找,导致驱动调试难度加大、费时费力。所以,在实现驱动之前就需要考虑到并发与竞争,而不是驱动都编写完了然后再处理并发与竞争。  
 
 
 
3. 保护什么
 前面一直说要防止并发访问共享资源,换句话说就是要保护共享资源,防止进行并发访问。  
 
 
 在程序中什么是共享资源?也就是保护的内容是什么? 
 
 我们保护的不是代码,  而是数据!某个线程的局部变量不需要保护,我们要保护的是多个线程都会访问的共享数据。  一个整形的全局变量  a  是数据,一份要打印的文档也是数据。 
 
 
 虽然我们知道了要对共享数据进行保护,怎么判断哪些共享数据要保护呢? 
 
 找到要保护的数据才是重点,而这个也是难点,  因为驱动程序各不相同,那么数据也千变万化,一般像全局变量,设备结构体这些肯定是要保 护的,至于其他的数据就要根据实际的驱动程序而定了。  
 
 当我们发现驱动程序中存在并发和竞争的时候一定要处理掉。