首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ucos在s3c2410上运行过程整体剖析-从main函数到UCOS初始化完毕(2)

ucos在s3c2410上运行过程整体剖析-从main函数到UCOS初始化完毕(2)

关于初始化硬件平台的部分前面已经说明了查看哪些资料,就不多说了。
讲解关于ucos的初始化前,我要说一下这个ucos操作系统的相关知识,以及我讲解这个操作系统的基本方法。
我们都知道操作系统的目标就是充分利用计算机提供的硬件资源,合理进行调度并为用户提供友好的借口。这些资源包括处理器(cpu),内存,外围设备等,而其中ucos是一个嵌入式的实时操作系统,它主要管理和调度的资源就是cpu。我们将剖析它是怎么实现cpu的较高的利用率的,以及是如何实现实时性的。分析一下我们平时用电脑那种既能听歌又能同时打游戏这样的功能是怎么做到的。分析我们平时看到的现象和真实的实际情况有什么不同点。嘻嘻
我们都知道cpu的核心是一个叫晶振的东西,它能产生固有的脉冲频率,cpu就在这种信号下有规律的工作,那操作系统是谁给提供这种时序性那,答案是定时器,定时器以固定的时间向cpu发出中断请求,而ucos的一些功能都是在定时器的中断服务程序里实现的。所以定时器是操作系统必须的硬件,有了定时器操作系统才有了生命。才能实现实时性!!!
因此,我将通过两条线路来讲解ucos操作系统的执行流程:
一:正常的执行流程
二:被定时器中断后的中断服务程序
需要注意的是这两条线路是交叉执行的,因为定时器中断是周期性的,所以不论正常程序执行到什么地方定时器中断都有可能发生。其实,就是因为这种打断性才使操作系统的多任务调度有了基础。这个当你充分从整体的角度理解了ucos操作系统,你就知道了。

前面说了,ucos主要管理的是处理机的调度,那调度什么那?其实一个程序可能因为某些原因不能一直占有处理机,比如说他在等待一个资源,它再占用处理机那就相当于占着茅坑不拉屎。所以在有操作系统的时候,就可以有多个程序在不同的时间里占用cpu,这样有执行环境的程序,我们给他取个名字叫任务或者进程。而ucos就是决定什么时候该那个任务运行的。
所以,在分析源码之前还是要说明一个重要的概念,那就是任务(进程)。
相信大家对计算机能同时干这么多活这一现象可能存在疑问,那是什么机制让我们的电脑做到了真正的三心二意那,那当然属操作系统了。它管理着我们的电脑到底该干什么工作了?上一个工作干到什么程度了。我们也知道程序是一段有顺序的解决问题的指令。我们的机器里面只有一个CPU,但可能有很多解决问题的程序,他们肯定要争夺CPU这个资源,怎么管理他们,让他们有条不紊的运行下去那。这是我们今天要讨论的问题,怎么样,你有什么好的想法吗?
其实,这个问题也很简单,比如咱们现在先不说什么程序代码。我们先说一个类似的问题。
让你带着5个小孩玩,你的任务就是看护这5个小孩,让他们不打架,不受伤害,玩的开心。
而你现在只有一个游戏机,而你现在就面临着这样一种情况,怎么利用这一个游戏机让所有的孩子都能玩好又不产生矛盾。
要是我解决这个问题的话,我可能会这样去做,跟孩子们说:因为只有一个游戏机,你们5个只能轮流着玩这一个游戏机,没人玩半小时,那至于谁先玩的问题,我们这样,今天谁先来的这里谁就先玩(即谁今天来的早谁就先玩)。好了,这个问题到现在为止解决了。不,到真正实施的时候可能会遇到一些问题,比如一个孩子玩够了半个小时,是让他自己自愿提出来我玩的时间到了还是有你在旁边计时并强制让其给另一个孩子玩。还有每个孩子玩的游戏进度都不一样,你可能还要保存每一个孩子玩的进度问题,因为每一个孩子都只关心自己玩的游戏而不关心别的事情。当然,还有一些其他的问题,一个孩子特别不懂事,非要提前玩游戏机,你还要考虑这个问题。当然,在实施过程中还有很多问题,你能想一想还有其他什么问题可能在这个过程中遇到吗?
呵呵,看似一件很简单的事情,做起来还真有难度。其实很多事情都是这样,在一件事情还没有真正做之前做一些计划和方案是很难的,因为你不知道会遇到什么临时情况。但我们一般会做计划,并且要考虑所有可能遇到的情况以及遇到这些情况的处理方案。
好了,闲言少叙,回归到我们要处理很多程序争夺一个CPU的问题。显然,程序没有小孩那么智能,它不能听懂一些规则。因此,我们必须把这些规则具体化,即用程序代码去实现这些规则。因为计算机只认识程序。
好了,上面一直说程序,这个很好理解,也就是一个算法。那这个算法怎么才能体现出它的具体价值那,恩,这是一个事。比如,你写了一个程序计算两个10以内的两个数的加法。那你的目的很明确就是输入两个10以内的数,而得到这两个数的结果。你可以通过计算机的输入设备来进行输入,可以利用输出设备来进行输出结果。而程序在计算机运行一遍的这个过程所产生的效果是我们想要的。那把程序中的代码一一运行产生效果的这个过程,原来那一段静止的代码就一步步动起来了。当然它运行起来了肯定会需要一些环境,这些环境当然是计算机硬件提供的了,关于程序运行到底需要哪些具体的环境,我们下面具体探讨。那我们给这个正在在计算机内部执行的这个程序起个名字。叫什么那?
别人已经起好了,叫进程了,或者任务。
现在大家明白什么叫进程了吧,其实就是一段代码加上这段代码在计算机内部运行时所需要的所有环境。不管现在它运行没运行,一段程序加上可在计算机内部运行的能力,我们给他起了个名字叫进程(可能大概的意思是正在运行的程序吧)。
这是我对进程(任务)的理解。这是在计算机操作系统中对底层最基本的一个抽象。在上面说的带小孩玩的例子中,每一个小孩就是一个进程(任务)。我会在下一个章节中具体以UCOS为例,具体讲解怎么高效的管理这些小家伙(进程或者任务)。
好了,下面说一下进程中所要包含的具体硬件环境,咱们就以arm920t为实例,说明在这上面运行的程序到底需要哪些环境,他们这些叫进程的小家伙生活在什么环境下那?我想你一定很想知道的。
我们都知道的,arm920t有运行模式,我们就选其中一个模式来说。
R0~R12这些寄存器是他们生活的必需品,还有sp(r13)堆栈指针,lr(r14)the linker register ,还有程序计数器PC(r15),还有就是当前程序运行状态寄存器CPSR,以及SPSR。
这些寄存器就是程序执行时的所有硬件环境。其实也很简单,哈。
你想一想,如果你把一个程序在某一时刻打断了,但是你把这些寄存器都保存到一个地方了,你下次再把这些内容都恢复到各个寄存器里面,那这个程序就按照原来被打断的地方开始执行喽。就相当于把这个小生命给暂定了,静止了,然后在一个合适的时候它又恢复了原来的生活。呵呵呵。
好,现在我们理解了什么是进程以及它生活的环境。那么只要我们能记住每个进程的状态,我们就可以管理他们了。你想管理他们那就要首先了解他们,并且能记忆他们被打断时的状态。这样我们就能恢复这个任务的所有状态了。如果我们有很好的调度算法,那就可以很好的管理他们啦。另外,我们的操作系统还要记录进程的运行状态,在ucos里包括,运行态,就绪态,阻塞态等状态,这样有利于管理这些进程。
下面说说操作系统一般是怎么记忆这些东西的,那就要定义一个数据结构用来记忆这些信息。这个东西起个名字叫任务控制块(TCB,task contorl block)。
我们看看这个ucos的任务控制块的结构:
我们跳过那些宏条件编译,只说明核心的部分。

typedef struct os_tcb {

    OS_STK          *OSTCBStkPtr;  /* Pointer to current top of stack */              

//这个是任务的堆栈的栈顶指针。我说一下,在ucos中每个任务都有自己的堆栈空间,用于保存程序运行中函数调用的情况(这点可以从c语言执行和堆栈这里知道栈的重要性)以及当发生任务切换时保存任务执行的状态。也就是那些寄存器的内容在发生任务切换时就都入到自己任务的堆栈里去。

#if OS_TASK_CREATE_EXT_EN > 0

    void            *OSTCBExtPtr;   /* Pointer to user definable data for TCB extension */

    OS_STK          *OSTCBStkBottom; /* Pointer to bottom of stack*/                                 

    INT32U           OSTCBStkSize; /* Size of task stack (in number of stack elements) */            

    INT16U           OSTCBOpt;      /* Task options as passed by OSTaskCreateExt()*/                 

    INT16U           OSTCBId;       /* Task ID (0..65535) */                                         

#endif

继承事业,薪火相传
返回列表