网站建设定价做曖免费网站
网站建设定价,做曖免费网站,打码挂机网站建设,北京市中海建设有限公司网站嵌入式Linux应用开发-驱动大全-同步与互斥② 第一章 同步与互斥②1.3 原子操作的实现原理与使用1.3.1 原子变量的内核操作函数1.3.2 原子变量的内核实现1.3.2.1 ATOMIC_OP在 UP系统中的实现1.3.2.2 ATOMIC_OP在 SMP系统中的实现 1.3.3 原子变量使用案例1.3.4 原子位介绍1.3.4.1… 嵌入式Linux应用开发-驱动大全-同步与互斥② 第一章 同步与互斥②1.3 原子操作的实现原理与使用1.3.1 原子变量的内核操作函数1.3.2 原子变量的内核实现1.3.2.1 ATOMIC_OP在 UP系统中的实现1.3.2.2 ATOMIC_OP在 SMP系统中的实现 1.3.3 原子变量使用案例1.3.4 原子位介绍1.3.4.1 原子位的内核操作函数 第一章 同步与互斥② 1.3 原子操作的实现原理与使用
在上面的第 2个失败例子里问题在于对 valid变量的修改被打断了。如果对 valid变量的操作不能被打断就解决这个问题了。 这可以使用原子操作所谓“原子操作”就是这个操作不会被打断。Linux有 2种原子操作原子变量、原子位。
1.3.1 原子变量的内核操作函数
原子变量的操作函数在 Linux内核文件 arch\arm\include\asm\atomic.h中。 原子变量类型如下实际上就是一个结构体(内核文件 include/linux/types.h)
特殊的地方在于它的操作函数如下(下表中 v都是 atomic_t指针)
1.3.2 原子变量的内核实现
注意SMP就是 Symmetric Multi-Processors对称多处理器UP即 Uni-Processor系统只有一个单核 CPU。 这些函数都是在 Linux内核文件 arch\arm\include\asm\atomic.h中。 atomic_readatomic_set这些操作都只需要一条汇编指令所以它们本身就是不可打断的。 问题在于 atomic_inc这类操作要读出、修改、写回。 以 atomic_inc为例在 atomic.h文件中如下定义
#define atomic_inc(v) atomic_add(1, v) atomic_add又是怎样实现的呢用下面这个宏
ATOMIC_OPS(add, , add) 把这个宏展开
#define ATOMIC_OPS(op, c_op, asm_op) \ATOMIC_OP(op, c_op, asm_op) \ATOMIC_OP_RETURN(op, c_op, asm_op) \ATOMIC_FETCH_OP(op, c_op, asm_op) 从上面的宏可以知道一个 ATOMIC_OPS定义了 3个函数。比如“ATOMIC_OPS(add, , add)”就定义了这 3个函数
atomic_add
atomic_add_return
atomic_atomic_fetch_add 或 atomic_fetch_add_relaxed 我们以 ATOMIC_OP(add, , add)为例看它是如何实现 atomic_add函数的对于 UP系统、SMP系统分别有不同的实现方法。
1.3.2.1 ATOMIC_OP在 UP系统中的实现
对于 ARMv6以下的 CPU系统不支持 SMP。原子变量的操作简单粗暴关中断中断都关了谁能来打断我代码如下(arch\arm\include\asm\atomic.h)
1.3.2.2 ATOMIC_OP在 SMP系统中的实现
对于 ARMv6及以上的 CPU有一些特殊的汇编指令来实现原子操作不再需要关中断代码如下(arch\arm\include\asm\atomic.h)
在 ARMv6及以上的架构中有 ldrex、strex指令ex表示 exclude意为独占地。这 2条指令要配合使用举例如下 ① 读出ldrex r0, [r1] 读取 r1所指内存的数据存入 r0并且标记r1所指内存为“独占访问”。 如果有其他程序再次执行“ldrex r0, [r1]”一样会成功一样会标记 r1所指内存为“独占访问”。 ② 修改 r0的值 ③ 写入strex r2, r0, [r1] 如果 r1的“独占访问”标记还存在则把 r0的新值写入 r1所指内存并且清除“独占访问”的标记把 r2设为 0表示成功。 如果 r1的“独占访问”标记不存在了就不会更新内存并且把 r2设为 1表示失败。 假设这样的抢占场景 ① 程序 A在读出、修改某个变量时被程序 B抢占了 ② 程序 B先完成了操作程序 B的 strex操作会清除“独占访问”的标记 ③ 轮到程序 A执行剩下的写入操作时它发现独占访问”标记不存在了于是取消写入操作。 这就避免了这样的事情发生程序 A、B同时修改这个变量并且都自认为成功了。 举报个例子比如 atomic_dec假设一开始变量值为 1程序 A本想把值从 1变为 0但是中途被程序B先把值从 1变成 0了但是没关系程序 A里会再次读出新值、修改、写入最终这个值被程序 A从 0改为-1。 在 ARMv6及以上的架构中原子操作不再需要关闭中断关中断的花销太大了。并且关中断并不适合SMP多 CPU系统你关了 CPU0的中断CPU1也可能会来执行些操作啊。 在 ARMv6及以上的架构中原子操作的执行过程是可以被打断的但是它的效果符合“原子”的定义一个完整的“读、修改、写入”原子的不会被别的程序打断。它的思路很简单如果被别的程序打断了那就重来最后总会成功的。
1.3.3 原子变量使用案例
现在可以使用原子变量实现只能有一个 APP访问驱动程序。代码如下
01 static atomic_t valid ATOMIC_INIT(1);
02
03 static ssize_t gpio_key_drv_open (struct inode *node, struct file *file) 04 {
05 if (atomic_dec_and_test(valid))
06 {
07 return 0;
08 }
09 atomic_inc(valid);
10 return -EBUSY;
11 }
12
13 static int gpio_key_drv_close (struct inode *node, struct file *file)
14 {
15 atomic_inc(valid);
16 return 0;
17 }
18 第 5行的 atomic_dec_and_test这是一个原子操作在 ARMv6以下的 CPU架构中这个函数是在关中断的情况下执行的它确实是“原子的”执行过程不被打断。 但是在 ARMv6及以上的 CPU架构中这个函数其实是可以被打断的但是它实现了原子操作的效果如下图所示
1.3.4 原子位介绍
1.3.4.1 原子位的内核操作函数
能操作原子变量再去操作其中的某一位不是挺简单的嘛不过不需要我们自己去实现内核做好了。 原子位的操作函数在 Linux内核文件 arch\arm\include\asm\bitops.h中下表中 p是一个 unsigned long指针。
1.3.4.2 原子位的内核实现 在 ARMv6以下的架构里不支持 SMP系统原子位的操作函数也是简单粗暴关中断。以 set_bit函数为例代码在内核文件 arch\arm\include\asm\bitops.h中如下
在 ARMv6及以上的架构中不需要关中断有 ldrex、strex等指令这些指令的作用在前面介绍过。还是以 set_bit函数为例代码如下
我不再使用原子位操作来写代码留给你们练习吧。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/88946.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!