【转载】µC/OS-II进程调度模型分析(PC移植版)

转自:http://aegiryy.net/?m=201011

µC/OS-II进程调度模型分析(PC移植版)

首先介绍一下µC/OS-II。

这是一个低功耗,基于优先级的抢占式的实时多任务操作系统内核。这个操作系统多用于嵌入式设备。

来自WIKIPEDIA

其实这也是源自嵌入式课程的作业,我有这个机会能够欣赏到µC/OS-II在windows上的移植。当我首先听到这个东西的时候,我惊讶了,一个操作系统怎么能移植到另一个操作系统上呢?操作系统应该直接面向硬件的阿,否则这玩意还有嘛意义?现在,我明白了。这个意义在于教学而非实用,可以让更多的人了解µC/OS-II的实现,而这个实现更多的是在于跟硬件无关层面的实现,包括IPC(Inter-Process Communication),进程调度,内存管理等方面。而且,这些也是操作系统最最核心的部分。

要分析这个进程调度模型,没有代码的展示和解释是不可想象的。其实很多时候,可怕的不是源代码本身,而是内心对于理解别人代码的畏惧。一份优秀的源代码,就像一本小说,有着跌宕起伏的情节,有着线索与线索之间的关联,这些都足够让人着迷。但是,µC/OS-II的代码虽然很清晰,但本身的结构并非完美,里面有着一些重复代码。这些让我产生了一个把这玩意从windows上移植到unix like的系统上,换而言之,就是对POSIX标准支持较好的系统上。

开始分析!

首先是关于临界区的,所谓临界区就是同一段时间不能有多个任务对临界区进行访问。在真实的硬件环境上往往是通过关中断的方式实现的,而在这个windows移植版上,是通过一个二元semaphore(如果童鞋们对于windows编程不甚了解,请先了解之,参看MSDN)。

µC/OS-II

抽象操作

Windows

OS_ENTER_CRITICAL

P

WaitForSingleObject
OS_EXIT_CRITICAL

V

ReleaseSemaphore

OSSemaphore = CreateSemaphore( NULL, 1, 1, NULL );

初始化

OSStartHighRdy函数(主要步骤概述,下同)

代码片段 描述
++OSRunning; 把系统状态更改为运行态
OSCtxSwW32Event = CreateEvent(NULL, FALSE, FALSE, NULL);

OSCtxSwW32Handle = CreateThread(NULL, 0, OSCtxSwW32, 0, 0, &dwID);

新建windows事件:上下文切换事件,第二个新建出来的线程会不停的等待这个事件。换而言之,当这个事件发生之后(SetEvent),线程会进行任务调度
OSTick32Handle = CreateThread(NULL, 0, OSTickW32, 0, 0, &dwID);

OSTickEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);

OSTickTimer = timeSetEvent((1000/OS_TICKS_PER_SEC), OSTimeCap.wPeriodMin, (LPTIMECALLBACK)OSTickEventHandle,  dwID, TIME_PERIODIC|TIME_CALLBACK_EVENT_SET);

该线程等待通过windows模拟出来的时钟中断,其实现是通过不断等待OSTickEventHandle事件。其中,timeSetEvent使得该事件每毫秒触发一次
SS_SP = (OS_EMU_STK*) OSTCBHighRdy->OSTCBStkPtr;

ResumeThread(SS_SP->Handle);

选出处于Ready态的且优先级最高的任务使之执行

调度函数OSCtxSw

代码片段 描述
n = SuspendThread(SS_SP->Handle); 暂停当前运行的任务
OSTCBCur = OSTCBHighRdy;

OSPrioCur = OSPrioHighRdy;

SS_SP = (OS_EMU_STK*) OSTCBHighRdy->OSTCBStkPtr;

上下文切换。保存被切换出去的任务,调入要被切换进来的任务。
ResumeThread(SS_SP->Handle); 执行调度进来的任务

时钟中断处理过程OSTickISR

代码片段 描述
OSIntEnter(); 统计当前进入的是第几级中断,在这个函数里会把级数+1
OSTimeTick(); 在这个函数中,每个处于等待态的任务会把OSTCBDly–,当有任务等待结束时,该任务会从等待态转换为就绪态
OSIntExit(); 该函数包含任务调度指示,下面会详述

时钟中断处理过程之OSTimeTick

代码片段 描述
OSTime++; 总的时间滴答数+1
while (ptcb->OSTCBPrio != OS_IDLE_PRIO) {

if (ptcb->OSTCBDly != 0) {

if (–ptcb->OSTCBDly == 0) {

更改为Rdy态;

调整OSRdyGrp;

调整OSRdyTbl;

}

}

ptcb = ptcb->OSTCBNext;

}

遍历整个TCBList,对于每个处于等待态的任务OSTCBDly-1。如果等待完毕,则执行伪代码所表示的意思。最后在while的最下面跳到下一个TCB。

时钟中断处理过程之OSIntExit

代码片段 描述
if (OSRunning == TRUE) { 判断当前操作系统状态是否为运行态
if (OSIntNesting > 0) {

OSIntNesting–;

}

如果当前中断是嵌套中断,则层数-1
if (OSIntNesting == 0) {

OS_SchedNew();

OSIntCtxSw();

}

}

如果已经是最顶层的中断,则进行调度,选取新的任务并进行切换。其中省略了部分代码,这部分代码判断当前优先级最高且处于Ready态的是否和当前任务相同,如果相同则无需调度

最后一点想法…

我想把这个内核移植到Unix Like系统上,所以我最近看了一下POSIX thread模型。似乎另外还缺关于timer的一些东西,等到把这些东西弄清除了再动手不迟。

--------------------------------------------------------------------------------------------------------------------

本来想弄个传送门的,usoc任务切换之类的还是能看懂的,VC部分真心没基础。为了方便还是转了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值