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

青春无悔

文章分类

全部博文(93)

文章存档

2015年(16)

2014年(77)

我的朋友

分类: C/C++

2015-03-08 22:51:36

下面是我从网上搜集到的关于全局变量使用的注意点:
 
1.      全局变量要少用,能不用就不用;
 
2.      在主程序外面只对全局变量做声明,不做定义;
 
3.      使用中断时,要加上使用的寄存器组;
 
4.      裸露的全局变量全部用结构体封装起来;
 
5.      中断与主程序共享全局变量,用函数(含临界段)封装起来;
 
6.      使用全局变量出错时,可以给它指定一个地址(注意:不要和当前使用的寄存器组发生冲突);
 
7.      将大部分全局/静态变量(特别是数组)定义到xdata段中;
 
8.      有些变量可能会随时改变,例如:在中断中赋值的变量,以及硬件修改的输入/输出寄存器等,在程序中使用这些变量时,最好加上“volatile”关键词,告诉C51编译器:
 
(1)不要优化该变量,例如相连的两个相同的赋值语句,第二个不要优化掉,因其处于不同“时刻”赋值结果可能不一样。
 
(2)每次取该变量值时要从其实际地址的寄存器取,不要从内存的副本中取,因其值可能随时比改变了。


51单片机解决中断和主程序共享全局变量的方法

所谓原子操作,并不是指一条指令,而是指一系列操作不能被打断. 
这种操作与临界区是密切相关的,可以说原子操作就是临界区引发出来的需求. 
以上是给大家提供资料查找的入口,下面我用通俗的话说说,但切不要认为自已看懂了就可以不去查以上相关资料了,知道啥叫"通俗"吗?呵呵.废话不多说: 
在多进程的系统里(比如多任务,比如中断服务程序),假如两组程序都要访问同一个资源,而作为程序员的你没有办法避免在一个进程访问完该资源之前,另一进程就来访问该资源,就出现了访问冲突,这就是临界区问题. 
举个实际例子:假如A进程用变量a作为临时存储区时,如果运行到一半中断发生了,而中断里也会用到该变量,等中断返回时,变量a中的内容已经被破坏了,进程A并不知道这一点,于是得到错误的运行结果. 
避免的办法看似简单:拿个变量来当标志,为0时表示没人用共享资源,为1时表示正在使用.使用时先检查该标志,为1时等待,为0时则置1,并使用资源,用完后将标志置回0,于是资源冲突问题就解决了. 
是吗?问题转移了----当你检查完变量,发现它为0,正要将它置1时,此时进程被打断,于是别的进程仍会毫不客气的使用该资源,要命的是在多任务系统中,当CPU控制权回来时,刚才使用这个资源的进程还没用完这个资源呢,于是出错了. 
可以看出来,必须有一种这样的指令:先检查某变量,当它为0时则置1并跳转,而这一系列过程不允许被打断,拥有这种能力的指令就叫作"原子操作指令".由于51没有这种指令,这也就是为什么楼上很多人说要关中断的原因了.事实上,关中断这种方式也用于我们桌面机系统!LINUX就用了很多关中断. 
虽然51没有上面说的这种指令,却有另一个指令:DJNZ---先减再检查,并根据比较结果跳转,而这足够完成临界区操作了.

系统初始化是必须事先将s置初值为1 
aqui_mutex: 
DJNZ  s, wait 
....共享资源操作代码(也就是临界区) 
INC s 
RET 
wait: 
INC s 
jmp aqui_mutex 
以上代码在任何情况下(跑飞不算,呵呵)不会发生两个进程同时进入临界区的情况. 
你一定会想到,假如将上面的代码写成一个子程序,那就可以作为一个标准函数供C调用了,恭喜你,这就是标准的信号量. 
关于"临界区","信号量","原子操作",这些词和概念都是操作系统里整天要讨论的东西,而没接触过操作系统的人很难想到困扰自已的问题原来早就有人已经作出了系统的描述并找到解决的方法了,所以说,并不是"用不上"的知识就可以不学,知识是有关联性的,更高级的系统往往也会有更高级的思想.你未必需要穿皮鞋,但你必须了解皮鞋跟草鞋的区别和各自的优缺点



阅读(2101) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~