首先聊一聊全局变量:

在慕课上学习浙大老师的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中需要注意的全局变量的更多相关文章

  1. ucos中的三种临界区管理机制

    熟悉ucos,或者读过Jean.J.Labrosse写过的ucos书籍的人,一定会知道ucos中著名的临界区管理宏:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL(). 同样 ...

  2. C/C++中static的用法全局变量与局部变量

    1.什么是static? static 是C/C++中很常用的修饰符,它被用来控制变量的存储方式和可见性. 1.1static的引入 我们知道在函数内部定义的变量,当程序执行到它的定义处时,编译器为它 ...

  3. ucos中信号量 事件标志 消息队列都怎么用

    信号量 事件标志和消息队列分别应用于什么场景(反正我学的时候有点闹不清,现在总结一下): 信号量和事件标志用于任务同步.详细来说,这个功能可以替代以前裸机中你打一个标记的功能,比如使用了一个定时器,5 ...

  4. python开发_python中的变量:全局变量和局部变量

    如果你在为python中的变量:全局变量和局部变量头疼,我想这篇blog会给你帮助 运行效果: 代码部分: #Python中的变量:全局变量和局部变量 #在很多语言中,在声明全局变量的时候,都喜欢把全 ...

  5. [Taro] taro中定义以及使用全局变量

    taro中定义以及使用全局变量 错误的姿势 // app.tsx文件中 class App extends Component { componentDidMount() { this.user = ...

  6. SQL Server中,常用的全局变量

    在SQL Server中,全局变量是一种特殊类型的变量,服务器将维护这些变量的值.全局变量以@@前缀开头,不必进行声明,它们属于系统定义的函数.下表就是SQL Server中一些常用的全局变量. 全局 ...

  7. Javascript中的局部变量、全局变量的详解与var、let的使用区别

    前言 Javascript中的变量定义方式有以下三种方式:1.直接定义变量,var与let均不写: a = 10; 2.使用var关键字定义变量 var a = 10; 3.使用let关键字定义变量 ...

  8. UCOS 中的中断处理

    最近遇到一个问题,当我在UCOS里调用系统延时"OSTimeDlyHMSM(0, 0, 0, 10)",程序进入硬件错误中断“HardFault_Handler”中. 我开始以为是 ...

  9. ucos中消息队列的应用(二)

    继续说任务间的通信. 本次的任务是在ISR中发送一个消息给任务,ucos的代码中的是非常之简洁和容易理解啊.创建,释放,等待,非常好理解,不再赘述. 说说我遇到的问题,数据帧接收完之后,向消息队列发送 ...

随机推荐

  1. pc端布局的一点思考

    编写pc端页面需要注意些什么? 1.自适应最小屏幕,在小屏幕上样式不能错乱. 在桌面屏幕各分辨率使用比例中可以看到各桌面分辨率的使用比例,日常pc端开发我们会考虑到适配1024宽度大小的屏幕. 对于管 ...

  2. MFC如何添加bmp文件和ICO文件

    1.添加BMP格式文件如下图所示: 2.添加ICO格式文件如下图所示:

  3. go语言学习--string、int、int64互相转换,字符串的截取,数组和字符串的转换

    下面总结了go中常用的转换 #string到int int,err:=strconv.Atoi(string) #string到int64 int64, err := strconv.ParseInt ...

  4. Python【每日一问】07

    问:请解释使用 *args 和 **kwargs 的含义 答: *args:可变参数,表示将实参中按照位置传值,多余的值都给 args,多余的实参被打包成 tuple(元组),然后传递给函数调用 # ...

  5. UIView和CALayer区别

    (1)首先UIView可以响应用户的触摸事件,Layer不可以. (2)View中frame getter方法,bounds和center,UIView并没有做什么工作:它只是简单的各自调用它底层的C ...

  6. spring入门-注解的使用

    说明: 使用注解和使用配置文件实现的功能是一样的,都是为了解耦,但是配置文件语法属于非编程语言法语,无法调试,难以定位bug,使用注解更易定位问题. 配置步骤 编译器必须先安装了STS插件 第一步 导 ...

  7. mysql 下的update select from的两种方式比较

    工作中遇到需要将一个表中的数据按照对应规则填入别的表中的情况 例如 表1 a a1    a2 11     90889 32     31241 12     52123 表2 b b1     b ...

  8. linux下安装nexus repository及Intellij Idea集成私有maven

    前段日子公司搞java项目,使用nexus repository搭建了私有maven库,现在把原来的私有nuget也迁到nexus repository上了,下面介绍下搭建流程: https://he ...

  9. Win 10更新版1709有哪些新功能值得关注!

    windows 10秋季创意者更新版1709发布已经有段时间了,也有很多用户选择升级这次更新的系统.那么,这次Win 10 更新版1709有哪些新功能值得关注呢?下面,一起随主机吧来看一看吧! 1. ...

  10. kettle在centos7下部署分布式集群

    首先安装三台centos7 ,分别配置好静态ip    ssh免密码登录     关闭防火墙 具体步骤这里不多说了 关于centos7配置静态ip大家可以参考:https://www.cnblogs. ...