一. 简介
当我们发现驱动程序中存在并发和竞争的时候一定要处理掉,接下来我们依次来学习一下 Linux
内核提供的几种并发和竞争的处理方法。
本文学习Linux内核提供的一种处理并发与竞争的方法:原子操作。
二. 原子操作简介
原子操作就是指不能再进一步分割的操作,一般原子操作用于变量或者位操作。假如现在要对无符号整形变量
a
赋值,值为
3
,对于
C
语言来讲很简单,直接就
是:
a = 3
但是
C
语言要先编译为成汇编指令,
ARM
架构不支持直接对寄存器进行读写操作,这里所指的寄存器是 Ram,即对内存地址的操作,比如,要借助寄存器
R0
、
R1
等来完成赋值操作。
假设变量
a
的地址为
0X3000000
,“
a=3
” 这一行
C
语言可能会被编译为如下所示的汇编代码:
ldr r0, =0X30000000 /* 变量 a 地址 */
ldr r1, = 3 /* 要写入的值 */
str r1, [r0] /* 将 3 写入到 a 变量中 */
上面的代码只是一个简单的举例说明,实际的结果要比示例代码复杂的多。从上述
代码可以看出,
C
语言里面简简单单的一句 “
a=3
”,编译成汇编文件以后变成了
3
句,那么程
序在执行时肯定是按照上面示例代码
中的汇编语句一条一条的执行。
假设现在线程
A要向
a
变量写入
10
这个值,而线程
B
也要向
a
变量写入
20
这个值,我们理想中的执行顺序如
下图
所示:
按照上图
所示的流程,确实可以实现线程
A
将
a
变量设置为
10
,线程
B
将
a
变量设
置为
20
。但是实际上的执行流程可能如下图
所示:
按照上图
所示的流程,线程
A
最终将变量
a
设置为了
20
,而并不是要求的
10
!线程
B
没有问题。这就是一个最简单的设置变量值的并发与竞争的例子。
要解决这个问题就要保证
示例代码
中的三行汇编指令作为一个整体运行,也就是作为一个原子存在。
Linux 内核提供了两组原子操作 API 函数,一组 是对整形变量进行操作的,一组是对位进行操作的。我们接下来看一下这些 API 函数。
Linux 内核提供了两组原子操作 API 函数,一组 是对整形变量进行操作的,一组是对位进行操作的。我们接下来看一下这些 API 函数。