关闭
搜索
搜索
本版
帖子
用户
热搜:
程序员
简洁模式
高级模式
用户组: 游客
消息
提醒
新听众
我关注的
帖子
道具
勋章
任务
设置
退出
请
登录
后使用快捷导航
没有帐号?
立即注册
设为首页
收藏本站
开启辅助访问
切换到窄版
登录
or
立即注册
快捷导航
搜索
首页
论坛
BBS
MCU单片机技术
程序员交流
嵌入式简易操作系统剖析(二)
[复制链接]
作者:
萌萌男神丶Lin
版块:
›
灌水·股票·程序员大本营·工作之余需要点阳光·我们不只是工程师
›
IT业界资讯
发布时间:
2018-12-15 22:19:29
1535
0
返回列表
萌萌男神丶Lin
当前离线
新手上路
新手上路, 积分 6, 距离下一级还需 44 积分
新手上路
新手上路, 积分 6, 距离下一级还需 44 积分
积分
6
发消息
楼主
电梯直达
萌萌男神丶Lin
发表于 2018-12-15 22:19:29
|
只看该作者
|
倒序浏览
|
阅读模式
冬天没回你消息,不是因为高冷,而是因为手冷。
CYoung
做一个有温度的公众号
这是我的第三十一
篇原创文章
哎,这周过的真特么的憋屈,在弄USB打印机,又要搞USB协议栈,主要是USB打印机真鸡儿操蛋,不懂就是建立不了数据连接,如果有懂的小伙伴给我支支招呗。
上周写了一些关于嵌入式系统的文章,这篇我们就稍微的深入了解下任务调度呗,在ucos中核心就是任务调度,好多大神都说ucos的金典就是任务的调度。所以这篇文章写的不好的地方,还请多多宽待。
在我们嵌入式领域中,一般只有颗CPU,但是我们要实现多任务,这就要求我们有自己的堆栈,程序代码,数据存储区等,这一系列就是决定一个任务独立的最基本的条件。这个多说句,咱们人也是一样的,人要独立也得有自己的私有财产,让我们自己自由分配,不然怎么算的上最基本的独立呢?
01
可重入与不可重入函数在多任务中还有一个问题,就是可重入函数与不可重入函数的概念。那什么是可重入函数,什么又是不可重入函数呢?举个例子,一个低优先级的任务正在运行,他在操作一个全局变量,可能已经改变它的数值,正想使用这个变量的时候,另一个高优先级的任务正好打断他们,也使用这个函数,改变了这个全局变量。
所以一般情况下可重入函数使用的数据为局部变量,不带静态局部变量的那种。还有一种如果有malloc和free的也不是可重入函数。这里有点比较重要的是,全局变量是系统各个任务共享的,所以在似乎用多任务操作系统中尽量不要使用全局变量。
如果两个任务共用一套数据,破坏原先的数据结构,这时候我们就引入两种方法解决:可重入函数的设计和互斥调用。互斥调用就是之前说的临界区。
02
临界区临界区函数要求是互斥的,意思是说一次仅允许一个任务使用公共资源,中断也不可以影响,这个是为了保障数据的可靠性和完整性,我们之前使用的临界区是关中断的方式,其实还有一些,例如:使用互斥信号量,关任务调度等等。
这里要注意的地方是,
在临界区的代码必须成对的出现
,否则会出现不可预测的问题。我们使用临界区的时候,临界区的代码尽量短,因为一直在临界区中,别的任务是无法有使用CPU的机会的,这样会影响多任务系统的使用性能。
03
任务堆栈大伙也知道,我们在创建任务的时候,除了会传入任务优先级,还会传入一个任务栈,这个任务栈其实就是一个全局变量的静态数组。为啥用数组呢?主要他是地址是线性的,我们在使用的时候,如果这个栈是递增栈,只需要将栈顶指针SP指向数组首元素;如果是递减栈,SP指针指向最后一个元素,这样就实现了一个任务的私有栈了。
要注意的是,我们传入的栈大小视情况设定,避免导致任务的栈溢出,出现不可预测的问题,甚至可能出现系统奔溃的问题。
到目前为止,我们只解决了一个任务栈的问题,但是还没有说明如何进行任务的切换调度的问题。我们要实现任务的切换,还有一个条件就是要知道各个任务的栈顶指针的变量。说白了就是要保存它,这里就引入一个任务控制块的概念。
04
任务控制块什么是任务控制块呢?简单的说就是系统记录任务执行的环境,在ucos中任务控制块内容贼鸡儿长,长到什么地步呢?结构体有60多行,反正就是一张图片放不下呗。内容包括当前任务栈位置,任务栈大小,任务状态等等。
是不是特别的长,这里列出两个简单的务控制块,只包含了任务的堆栈指针和任务延时节拍数。
这个任务块结构体有点要注意的是,任务栈的栈顶凡在第一个位置,为什么这样做呢?原因是结构体首元素的首地址和结构体的地址是相同的,我们访问结构体的第一个元素,只需要得到结构体的地址即可。这个方式的好处我在之前的文章有介绍。感兴趣回头瞅瞅。
任务控制块是任务切换中的关键,也是任务的唯一标识,他里面保存任务的所有信息,他将任务的代码与数据链接起来,我们只要找到任务控制块就能找到任务的所有资源信息。
任务的三要素分别为:任务程序代码,任务私有堆栈和任务控制块。看下图可能就能了解任务控制块的重要性了。
目前为止,我们了解了任务的调度过程,但是还是少了一些细节,就是任务是如何进行切换的。这里就涉及到一些arm汇编的问题了,关于汇编我也不是很懂,反正不会就百度呗。
还有一点比较重要,就是在C语言中,我们是不可以直接访问SP指针,只能用汇编的形式,我们先定义一个结构体指针指向当前任务块,然后用汇编把当前任务的栈赋值给SP指针即可。代码示例如下:
汇编代码如下:
任务切换时,把当前任务的现场数据保存在自己的任务栈里面,再把待运行的任务的数据从自己的任务栈装载到 CPU 中,改变 CPU 的 PC,SP,寄存器等。可以说,任务的切换是任务运行环境的切换。而任务的运行环境保存在任务栈中,也就是说,任务切换的关键是把任务的私有堆栈指针赋予处理器的堆栈指针 SP。部分代码示例如下:
任务调度的汇编函数示例如下:
上面的代码看不同没关系,我们只需要知道的他是怎么实现任务切换的的就可以了,毕竟我们并不是写操作系统的,任务切换流程图如下:
好吧,这篇文章先写到这里,我想可能没有多少人能耐心的看到这里,能看到这里的人,个人觉得是真正想了解系统的人。再者我写的也比较简单,因为微信文章与文档还有差别的,只是给大伙介绍为主,并不是以实现为目的。
那就这样吧,周末愉快,大伙。还有还有,有了解USB协议栈的可以带我学习学习,感激不尽!
-END-
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有帐号?
立即注册
收藏
0
相关帖子
•
vagrant、docker、virtualbox之间的区别
•
Xmanager使用教程:如何在Linux系统上安装Xterm应用
•
开源项目EasyDarwin编译:Linux系统下编译运行最新EasyDarwin的步骤介绍
•
硬核观察|Python之父对Rust、Go、Julia和TypeScript的看法
•
推荐10个不错的网络监视工具,建议收藏!
•
干货|手把手带你搞定4大容器网络问题
•
Nyxt浏览器:一个受Emacs和Vim启发的面向键盘的网页浏览器|Linux中国
•
十个问题理解Linuxepoll工作原理
•
对话胡伟武:和国产CPU一起突围的20年
回复
使用道具
举报
返回列表
高级模式
B
Color
Image
Link
Quote
Code
表情
@朋友
您需要登录后才可以回帖
登录
|
立即注册
本版积分规则
发表回复
回帖后跳转到最后一页
浏览过的版块
linux
快速回复
返回顶部
返回列表