ucos中需要注意的全局变量
首先聊一聊全局变量:
在慕课上学习浙大老师的C语言课程的时候,翁恺老师一直在强调在程序中我们要避免使用全局变量,C语言的程序员(尤其像我这样的野生程序员)为了方便,经常会不顾这个编码规范。全局变量有一些显而易见的好处:全局可见,内存地址固定,读写效率高。比起优点来,全局变量的槽点更多:1)学过面向对象语言的同学会更加谨慎的使用全局变量,这破坏了函数的封装性能,降低了函数的可移植性。2)使代码可读性差,大型程序里面简直是灾难 3)生存期长,会占用较多的内存单元。
最近在看一本书叫《信息系统设计与分析》,里面从软件工程的角度也阐述了全局变量的危害。优秀的软件设计应尽可能达到高内聚低耦合。
内聚是指一个模块各个元素间彼此结合的紧密程度。
耦合是指模块之间互相连接的紧密程序。(关于这个话题,可以看一下其他博主的博文)全局变量毫无疑问会增加系统的耦合度。因此,这也是我们慎用全局变量的理由
ucos中需要注意的全局变量:
从裸机到ucos需要深刻转换的一点是ucos是一个可剥夺型的多任务内核,这意味着ucos总是执行当前优先级最高的就绪任务。全局变量生存期从程序执行到结尾,作用域是从变量定义开始到源文件结束。这意味着在ucos这样的可剥夺式的系统中,必须保障对全局变量的独占式访问。否则,有可能会出现任务间的竞争和数据破坏。
在《嵌入式实时操作系统ucos3》中举了一个关于时间更新的例子很有力的说明了全局变量在任务切换时不做保护带来的隐患:
u8 Seconds;
u8 Minutes;
u8 Hours;
void TimeOfDay(void *p_arg)
{
(void)p_arg;
OS_ERR err; while (DEF_TRUE) { /* Task body, always written as an infinite loop. */ OSTimeDlyHMSM(, , , ,
OS_OPT_TIME_HMSM_STRICT,
&err);
Seconds++;
if(Seconds > )
{
Seconds = ;
Minutes++;
if(Minutes > )
{
Minutes = ;
Hours++;
}
if(Hours > )
{
Hours = ;
}
}
}
}
假如在模块执行完Minutes = 0;这一行代码时,一个中断发生了,并使得一个具有比void TimeOfDay(void *p_arg)更高优先级的任务进入了就绪表,那么在中断结束返回后,TimeOfDay()就会被这个更高优先级的任务抢占而无法继续运行。一旦高优先级的任务想要从时钟模块中获取时间,那么由于中断前时钟模块的小时值没有更新,那么所读到的将会是一个与正确时间相差整整一个小时的错误值。
这里的时钟模块就是一个共享资源,在ucos中必须对此加以保护,保证对共享资源的独占访问。
PS:以上ucos部分的内容皆来自于《嵌入式实时操作系统uc/OS-III》一书的第十三章
ucos中需要注意的全局变量的更多相关文章
- ucos中的三种临界区管理机制
熟悉ucos,或者读过Jean.J.Labrosse写过的ucos书籍的人,一定会知道ucos中著名的临界区管理宏:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL(). 同样 ...
- C/C++中static的用法全局变量与局部变量
1.什么是static? static 是C/C++中很常用的修饰符,它被用来控制变量的存储方式和可见性. 1.1static的引入 我们知道在函数内部定义的变量,当程序执行到它的定义处时,编译器为它 ...
- ucos中信号量 事件标志 消息队列都怎么用
信号量 事件标志和消息队列分别应用于什么场景(反正我学的时候有点闹不清,现在总结一下): 信号量和事件标志用于任务同步.详细来说,这个功能可以替代以前裸机中你打一个标记的功能,比如使用了一个定时器,5 ...
- python开发_python中的变量:全局变量和局部变量
如果你在为python中的变量:全局变量和局部变量头疼,我想这篇blog会给你帮助 运行效果: 代码部分: #Python中的变量:全局变量和局部变量 #在很多语言中,在声明全局变量的时候,都喜欢把全 ...
- [Taro] taro中定义以及使用全局变量
taro中定义以及使用全局变量 错误的姿势 // app.tsx文件中 class App extends Component { componentDidMount() { this.user = ...
- SQL Server中,常用的全局变量
在SQL Server中,全局变量是一种特殊类型的变量,服务器将维护这些变量的值.全局变量以@@前缀开头,不必进行声明,它们属于系统定义的函数.下表就是SQL Server中一些常用的全局变量. 全局 ...
- Javascript中的局部变量、全局变量的详解与var、let的使用区别
前言 Javascript中的变量定义方式有以下三种方式:1.直接定义变量,var与let均不写: a = 10; 2.使用var关键字定义变量 var a = 10; 3.使用let关键字定义变量 ...
- UCOS 中的中断处理
最近遇到一个问题,当我在UCOS里调用系统延时"OSTimeDlyHMSM(0, 0, 0, 10)",程序进入硬件错误中断“HardFault_Handler”中. 我开始以为是 ...
- ucos中消息队列的应用(二)
继续说任务间的通信. 本次的任务是在ISR中发送一个消息给任务,ucos的代码中的是非常之简洁和容易理解啊.创建,释放,等待,非常好理解,不再赘述. 说说我遇到的问题,数据帧接收完之后,向消息队列发送 ...
随机推荐
- MapReduce作业的工作原理
在Hadoop中,我们可以通过Job对象的submit()方法来运行MapReduce作业,也可以调用waitForCompletion()用于提交以前没有提交过的作业,并等待它的完成.其中,subm ...
- 3、redis使用场景
现代高并发复杂系统面临的挑战 现代系统随着功能的复杂化,各种各样需求层出不穷,面对愈加复杂话的业务系统.越来越庞大的用户群体,以及用户对体验的要求越来越高,性能就变得更加重要. 抛开代码逻辑.服务器性 ...
- consul配置参数大全、详解、总结
命令行选项 以下选项全部在命令行中指定. -advertise - 通告地址用于更改我们通告给集群中其他节点的地址.默认情况下,-bind地址是通告的.但是,在某些情况下,可能存在无法绑定的可路由地址 ...
- AX2012 ERP 维度相关表数据关系图
AX2012比AX2009可怜的几个维度来说,太丰富了,可以无数个啊.维度多了,如何使用以及管理是个问题.这个需要在做调研时,充分分析讨论确定.以下为维度表关联关系,在做SQL取值时需要了解下,比如在 ...
- SpringBoot aop 注解 数据权限校验
注解类: @Retention(RetentionPolicy.RUNTIME) public @interface DataAuthValid { //位置 public int index() d ...
- thinkphp5在Linux下Nginx配置问题解决
首先tp5的访问目录指向到webroot/public文件夹中. thinkphp的url访问:http://serverName/index.php(或者其它应用入口文件)/模块/控制器/操作/[参 ...
- Centos7 系统下怎么更改apache默认网站目录
当我们在Centos7中配置好Apache时,发现apache默认解析目录是在 /var/www/html,也就是说当访问服务器 IP 或者本地 localhost 时,默认定位到这个目录里的 ind ...
- 初识异步、并发处理纯代码及Demo
多线程Thread 处理 Thread thread = new Thread(()=> { ; i < ; i++) { Console.WriteLine("这是第" ...
- mysql中的int和tinyint、varchar和char、DateTime和TimeStamp区别
一.int和tinyint的区别 大小: tinyint在mysql中占用1个字节 即: 1 bytes = 8 bit ,一个字节最多可以代表的数据长度是2的8次方:11111111 = 256 在 ...
- 【MySQL】5.7 复制
参考:http://www.cnblogs.com/zhoujinyi/p/5704567.html 参考:http://www.innomysql.com/article/25656.html 参考 ...