Chinaunix首页 | 论坛 | 博客
  • 博客访问: 203257
  • 博文数量: 93
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 978
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-10 15:46
个人简介

青春无悔

文章分类

全部博文(93)

文章存档

2015年(16)

2014年(77)

我的朋友

分类: C/C++

2015-04-01 20:27:12

“非原子操作”是相对于“原子操作”而言。

先来个例子(读-改-写 操作):
以下展现的是一段C代码和等效的ARM7汇编代码

C代码:
/* The C code being compiled. */ 
155: PORTA |= 0x01;


汇编代码:
/* The assembly code produced. */ 
0x00000264 481C LDR R0,[PC,#0x0070]  ; Obtain the address of PORTA 
0x00000266 6801 LDR R1,[R0,#0x00]     ; Read the value of PORTA into R1 
0x00000268 2201 MOV R2,#0x01           ; Move the absolute constant 1 into R2 
0x0000026A 4311 ORR R1,R2             ; OR R1 (PORTA) with R2 (constant 1) 
0x0000026C 6001 STR R1,[R0,#0x00]     ; Store the new value back to PORTA 

这是一个” 非原子” 操作,因为完成整个操作需要不止一条指令,所以操作过程可能
被中断。考虑如下情形,两个任务都试图更新一个名为PORTA 的内存映射寄存器: 
1.任务A 把PORTA 的值加载到寄存器中——整个流程的读操作。 
2.在任务A 完成整个流程的改和写操作之前,被任务B 抢占。 
3.任务B 完整的执行了对PORTA 的更新流程,然后进入阻塞态。 
4.任务A 从被抢占处继续执行。其修改了一个 PORTA 的拷贝,这其实只是寄存
器在任务A 回写到PORTA 之前曾经保存过的值。 
任务A 更新并回写了一个过期的PORTA 寄存器值。在任务A 获得拷贝与更新回
写之间,任务B 又修改了PORTA 的值。而之后任务A 对PORTA 的回写操作,覆盖
了任务B 对PORTA 进行的修改结果,效果上等同于破坏了PORTA 寄存器的值。 
虽然是以一个外围设备寄存器为例,但是整个情形同样适用于全局变量的读- 改-写
操作

变量的非原子访问 
更新结构体的多个成员变量,或是更新的变量其长度超过了架构体系的自然长度
( 比如,更新一个 16位机上的32位变量) 均是非原子操作的例子。如果这样的操作被中
断,将可能导致数据损坏或丢失。
阅读(877) | 评论(0) | 转发(0) |
0

上一篇:百度网盘资源汇总

下一篇:函数重入

给主人留下些什么吧!~~