uCOSII实时操作系统通信机制之内核分析.docx

上传人:sk****8 文档编号:3150332 上传时间:2019-05-23 格式:DOCX 页数:5 大小:21.25KB
下载 相关 举报
uCOSII实时操作系统通信机制之内核分析.docx_第1页
第1页 / 共5页
uCOSII实时操作系统通信机制之内核分析.docx_第2页
第2页 / 共5页
uCOSII实时操作系统通信机制之内核分析.docx_第3页
第3页 / 共5页
uCOSII实时操作系统通信机制之内核分析.docx_第4页
第4页 / 共5页
uCOSII实时操作系统通信机制之内核分析.docx_第5页
第5页 / 共5页
亲,该文档总共5页,全部预览完了,如果喜欢就下载吧!
资源描述

1、C/OS-II 通信机制之内核分析摘要: 本文主要着重对 C/OS-III 通信机制的内核分析,研究 C/OS-II 内核通信机制的实现方式及实现的技巧,同时分析其中不足之处。1引言C/OS-II 是 一 种 可 移 植 的 , 可 植 入 ROM 的 , 可 裁 剪 的 , 抢 占 式 的 , 实 时 多 任务 操 作 系 统 内 核 。 它 被 广 泛 应 用 于 微 处 理 器 、 微 控 制 器 和 数 字 信 号 处 理 器 。uC/OS-II 只 是 一 个 实 时 操 作 系 统 内 核 , 它 仅 仅 包 含 了 任 务 调 度 , 任 务 管 理 , 时间 管 理 , 内 存

2、 管 理 和 任 务 间 的 通 信 和 同 步 等 基 本 功 能 。 没 有 提 供 输 入 输 出 管 理 , 文 件 系统 , 网 络 等 额 外 的 服 务 。 但 由 于 uC/OS-II 良 好 的 可 扩 展 性 和 源 码 开 放 , 这 些 非 必 须 的功 能 完 全 可 以 由 用 户 自 己 根 据 需 要 分 别 实 现 。C/OS-II 这 款 操 作 系 统 内 核 简 单 易 学 , 通 过 对 其 源 代 码 的 分 析 , 可 以 加 深 我 们 对操 作 系 统 内 核 的 理 解 , 为 学 习 linux 等 大 型 操 作 系 统 打 下 基 础

3、。2 操 作 系 统 中 任 务 间 的 通 信 机 制内核中多个任务之间不可避免的存在相互协同的关系,来完成一定的内核功能。这种协同最直观的就是任务间相互通信。包括VxWorks 等所有的嵌入式操作系统一般都会提供许多任务间通信的方法,通常包括:(1)共享内存,数据的简单共享。(2)信号量,基本的互斥和同步。(3)消息队列和管道,同一CPU 内多任务间消息传递。(4) Socket 和远程调用,任务间透明的网络通信。(5)Signals,用于异常处理。在 C/OS-II中设计了五种通讯机制,或者说是同步机制,分别是信号量(semaphore) ,互斥体(mutual exclusion se

4、maphore) ,事件组(event flag) ,邮箱(message box)和队列(queue) 。3. uC/OS-II中 通 信 机 制 实 现 的 方 式 分 析在 uC/OS-II 中 是 如 何 通 信 机 制 呢 ? 这 几 种 通 信 机 制 有 什 么 关 系 ? 或 者 说 有 什 么 共同 点 有 什 么 不 同 点 ? 在 实 现 上 有 哪 些 步 骤 是 相 同 的 ? 下 面 将 就 这 几 个 问 题 进 行 分 析 论 述 。我 们 知 道 通 信 机 制 是 发 生 在 任 务 之 间 的 , 换 句 话 说 任 务 与 通 信 机 制 存 在 着 关

5、 联 。在 内 核 又 是 如 何 处 理 这 种 关 联 呢 ? 通 信 机 制 具 体 来 说 是 信 号 量 ,互 斥 量 , 邮 箱 , 队 列等 。 通 信 机 制 协 调 的 关 系 一 般 是 针 对 两 个 以 上 的 任 务 , 比 如 说 当 两 个 任 务 互 斥 的 访 问 共享 资 源 , 就 需 要 一 个 互 斥 量 , 这 个 互 斥 量 就 关 联 着 这 两 个 任 务 。 同 样 的 道 理 , 其 他 通 信机 制 也 是 关 联 着 两 个 以 上 的 任 务 。 那 么 设 计 内 核 时 就 要 考 虑 如 何 将 他 们 的 关 系 有 效 协

6、调地 统 一 管 理 起 来 。在 内 核 中 是 通 过 一 个 事 件 控 制 块 来 实 现 通 信 机 制 与 任 务 的 联 系 。 这 里 所 说 的 事 件就 是 指 任 务 间 进 行 通 信 时 传 递 信 号 的 统 称 。 这 里 其 实 是 利 用 到 了 一 种 抽 象 的 思 想 , 即 将各 种 通 信 机 制 的 共 同 点 抽 象 出 来 , 于 是 内 核 就 设 计 了 一 个 事 件 控 制 块 的 数 据 结 构 , 这 个数 据 结 构 是 所 有 通 信 机 制 都 会 用 到 的 , 这 样 的 设 计 就 节 省 了 不 少 代 码 , 因 为

7、 有 共 同 点 意味 着 有 重 复 代 码 。既 然 知 道 了 事 件 控 制 块 是 实 现 通 信 机 制 代 码 共 享 的 关 键 , 那 么 下 面 我 们 就 来 分 析下 它 的 数 据 结 构 。typedef structINT8U OSEventType; /事件类型INT8U OSEventGrp; /等待任务所在的组INT16U OSEventCnt; /当事件是信号量时的计数器void *OSEventPtr; /指向消息或消息队列的指针INT8U OSEventTblOS_EVENT_TBL_SIZE; /等待任务列表 OS_EVENT; 第 一 个 变 量

8、是 事 件 类 型 , 它 可 以 是 信 号 量 , 互 斥 型 信 号 量 , 邮 箱 或 是 消 息 队 列 中的 一 种 。 OSEventPtr 是一个泛型指针,只在所定义的事件是邮箱或者消息队列时才会用到,用来指向一个消息,指针类型设计成泛型的,这是一个设计技巧,因为还不知道具体的消息是什么样的数据结构类型。OSEventGrp 和 OSEventTblOS_EVENT_TBL_SIZE用来控制等待某事件的任务,换句话说是等待某事件的任务列表信息。通过查询这个列表信息可以知道有哪些任务在等待这个事件。OSEventCnt 是计数器,当事件定义的是信号量或者是互斥型信号量时会用到。从

9、这个事件控制块的数据结构我们可以看出,它是具有抽象性质的,即可以定义成不同的事件类型,可根据具体情况进行不同类型的定义,它具有一定的通用性,又具有一定的针对性(如 OSEventPtr 只对邮箱或者消息队列有用) 。也就是说这样的设计抽象的程序不够,存在着一定的数据冗余,比如说当事件定义成信号量时,根本用不到 OSEventPtr 这个变量,它就相当是一个冗余变量,这是内核设计存在的一个缺陷。下面分析下事件控制块是如何管理其等待的任务。首先等待一个事件的任务可能是多个,而且任务加入等待列队的时间不一样,那么又如何合理地安排它们的等待顺序呢?在内核中又是如何实现的呢?当一个事件发生后,该事件的等

10、待事件列表中优先级最高的任务得到该任务。事件等待列表是利用 OSEventGrp 和 OSEventTblOS_EVENT_TBL_SIZE这两个变量来控制的。在 C/OS-II 实 时 操 作 系 统 内 核 中 最 多 能 控 制 64 个 任 务 。 也 就 是 说 任 务 列 表 必 须 能 表示 出 64 个 任 务 的 信 息 。 在 内 核 中 , 所 有 任 务 优 先 级 被 分 成 8 组 ( 每 组 8 个 优 先 级 ) ,分 别 对 应 于 OSEventGrp 的 8 位,这个变量被定义成 8 位的数据类型,每一位都用来指示是否有任务在等待事件发生的状态。当某组中有

11、有任务处于等待事件的状态时,OSEventGrp 对应的位就会被置 1。相应地,该任务在 OSEventTbl中对应位也被置 1。那么实现一个任务置于等待事件的任务列表中或者从等待事件的任务列表中使任务脱离等待状态或者在等待事件列表中查找优先级最高的任务的算法又怎么样的呢?将一个任务插入到等待事件的任务列表中:pevent - OSEventGrp |= OSMapTblprio 3;pevent - OSEventTblprio3 = OSMapTblprio 从等待事件的任务列表中使任务脱离等待状态:if (pevent - OSEventTblprio 3 在等待事件的任务列表中查找优先

12、级最高的任务:y = OSUnMapTblpevent - OSEventGrp;x = OSUnMapTblpevent - OSEventTbly;prio = (y 3) + x;从上述代码中可以看到用到了两个数组,一个是 OSMapTbl,一个是 OSUnMapTbl,它们是已经定义的映射表,如 OSMapTbl的内容是1, 2,4,8,16,32,64,128,这个数组出现的目的是为了更方便的置位。说白点,使用 OSMapTblindex的作用是更方便的把某个数值的第 index 位置 1。从上述的代码中我们可以看出算法的原理是:任务的优先级的最低 3 位决定了该任务在相应的 OSE

13、ventTbl中的位置,紧接着的高 3 位则决定了该任务优先级在OSEventTbl中的字节索引。处理事件与任务的关系时需要处理的三个共同问题:使一个任务进入就绪态,使一个任务进入等待某事件发生的状态,由于等待超时而将任务置为就绪态。分别对应于三个函数。这样的处理可以避免大量重复的代码,因为这些处理是所有通信机制所必须的,没有必要为每个通信机制就写一个独特的函数来处理。下面提出一个问题,既然事件控制块是所有通信机制的抽象,那么具体的通信机制又是如何与事件控制块进行关联呢?下面我以信号量的设计为例来进行说明。创建一个信号量时即要先创建一个事件控制块,在内核中是从事件空闲块中取出一个事件控制块,然

14、后对这个事件控制块的数据变量进行赋值,使之成为表示一个信号量的数据结构。并将些事件控制块进行初始化,初始化的主要工作是将事件的任务等待列表清空为 0。并把创建好的事件控制块指针返回。这个返回的事件控制块指针就是一个信号量,等待信号量与发送信号量都是用到这个指针的。那么某个任务发送一个创建好的信号量又是如何实现的?信号量在创建时会有个计数器,这个计数器标志着可用资源数,创建信号量时可以初始为 0。当一个任务发送一个信号量时,需要考虑几个问题:发送的信号量是否真的存在?有没有任务在等待这个信号量?信号量的计数器值有没有超过范围?当发送的信号不存在时或者信号量的计数器的值超过范围要直接返回一个错误代

15、码。如果有任务在等待这个信号量,那么就让这个任务等待列表中最高优先级的任务马上进入就绪态准备运行。计数器不用加 1,因为资源已经消耗了(有任务得到信号量进入就绪态)。如果没有任务在等待这个信号量,那么计数个器值加1,表示又多一个信号量可用。而任务等待一个信号量的实现方式又是如何设计的呢?内核支持超时等待机制,即可以限定等待的时间,在限定的时间内没有收到信号量时任务会自动进入就绪态准备运行。等待一个信号量本质上就判断一个信号量的计数值是否大于 0,如果大于 0 说明信号量可用,等待的信号量已经到达,任务可以执行后面的程序,然后还要把计数值减 1,表示消耗了一个信号量。如果计数值为 0(等待的信号

16、量还没有到),那么任务要进入休眠态,实现的方法是将限定等待的时间值任务赋给任务的延时值。任务控制块的数据结构中有一个变量是延时值,用来控制休眠的时间,改变这个延时值就相当于是改变这个任务的休眠时间,一般处于就绪态的任务延时值是为 0 的。任务进入就绪态后就重新进行任务的调度。当这个任务从休眠态回复到运行态时有两种可能:一种是超时了,一种是在限定的时间内得到了一个信号量,那么在恢复运行态时就要进行一个判断。那现在提出一个问题是:如何区分这两种情况呢?内核是作何处理的呢?原来任务控制块中有一个变量是状态变量,这个变量标志着任务是处于何种状态,是在等待一个信号量还是在已经得到了一个信号量。任务在休眠

17、前这个变量表示的是任务处于等待一个信号量的状态。如果等待超时后还没有得到信号量,那么这个状态变量是没有发生变化的,任务恢复运行时可以判断这个变量,如果表示处于等待一个信号量的状态,那么就意味着等待超时了,则任务就要进入就绪态准备运行。如果任务在进入休眠态期间,有其他任务释放信号量时,就会发现有任务在等待这个信号量,并将这个任务处于就绪态准备运行,同时改变这个任务的状态变量,让它表示这个任务已经得到信号量了。任务恢复运行时就会知道是得到了信号量,然后可以处理后面的内容。通过以上分析我们可以很清楚的知道事件控制块是如何与具体的通信机制进行了结合。这个有点像面向对象的思想,如果抽象类一般是父类,其子

18、类就是具体实现的类。创建一个子类后返回的指针值可以用抽象类的指针指向它。与之类似的是,创建了一个信号量后返回的却是一个事件控制块指针,但是此指针已经不是指向单纯的事件控制块了,它具体的信息是一个信号量。其他的通信机制也是类似的用法。互斥型信号量与一般的信号量实现方式类似,不过在这个内核中互斥型信号量还可以实现优先级反转,具体情况在此不作论述。下面对消息邮箱的设计进行一个说明,进一步说明内核中是如何将事件控制块与具体通信机制进行结合的。首先要介绍的是内核是如何实现创建一个邮箱的。邮箱意味着传递的是一个消息,在这个实时操作系统中邮箱只允许存放一个消息。消息的类型可以自定义。创建邮箱函数需要传递进来

19、一个消息指针,类型是泛型的。创建一个事件控制块(在内核中是从空闲的事件控制块的链表中取出的),然后对这个事件控制块的数据变量初始化,使之具有邮箱的特征,这与信号量的创建有点类似。传递进来的消息指针也会保存在事件控制块中,最后把这个事件控制块的指针返回。向邮箱发送一则消息的实现方式。向邮箱发送一则消息的函数要两个参数,一个是定义为邮箱的事件控制块指针,一个是要发送的消息的指针。发送要要先进行判断有没有任务在等待这个邮箱中的消息,如果有任务在等待这个邮箱里的消息,则将等待列表中优先级最高的任务置于就绪态。并重新调度任务。如果还没有任务在等待这个邮箱里的消息,那么下一步就是要判断这个邮箱里有没有存有

20、消息,如果已经存有消息了,那么就要返回一个表示消息已满的错误代码,因为邮箱只支持存放一个消息。如果邮箱是空的,那么就将要发送的消息的指针存放在邮箱中,即赋给事件控制块里的一个表示消息的指针变量。等待邮箱里消息的实现方式。邮箱等待也支持等待超时机制,这个机制与前文所述的信号量等待超时机制相类似。判断邮箱中是否有消息的方法很简单,只要判断下事件控制块中指向消息的指针变量是不是为 0,如果为 0 说明消息是空的,还没有等到消息,如果是非空的,说明消息已经到了,将此消息返回,并把邮箱中的消息清空,清空的方法也很简单,只需将消息指针指向 0 即可。如果消息为空,那么任务就要进入休眠态,这个机制与信号量的机制一样,在此不作过多论述。当任务从休眠态中恢复运行时又再进行一次判断看消息是否为空,如果不为空说明在休眠态期间邮箱已经有任务往里面存放消息了。如果为消息为空,说明是等待超时了,要将任务置于就绪态。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 重点行业资料库 > 建筑建材

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。