⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 嵌入式操作系统的内核研究.txt

📁 嵌入式操作系统是嵌入式系统应用的核心
💻 TXT
字号:
嵌入式操作系统的内核研究
 
引言:

嵌入式系统被定义为:以应用为中心,以计算机技术为基础,软件硬件可裁减,适应应
用系统对功能,可靠性,成本,体积,功耗等严格要求的专用计算机系统。随着现代计算机
技术的飞速发展和互联网技术的广泛应用,嵌入式系统扮演了越来越重要的角色,被广泛应
用于信息电器、移动计算机设备、网络设备和工控仿真等领域。从八十年代起,国际上就有
一些IT 组织、公司,开始进行商用嵌入式系统的研发。这其中涌现了一些著名的嵌入式系
统,如windriversystem 公司的VxWorks 就是实时嵌入式操作系统的代表。但是商用产品的
造价十分昂贵,而uc/os-II 操作系统,是当前得到广泛应用免费且公开源码的嵌入式操作系
统。而包括这两个系统在内的绝大多数的嵌入式操作系统都采取了高性能的微内核设计。

第一章内核概述

1.1. 内核定义
在传统的操作系统结构中,通常把操作系统的全部或者大部分功能都作为操作系统的内
核,它们的层次主要表示为调用关系,但是现代操作系统的一个突出特点是把把更多的代码
放到更高的层次:用户层中去。尽最大努力把大部份操作系统成分和功能放到用户模式去运
行,希望留下一个尽量小的内核,他们完成操作系统最基本的核心功能,这称之为内核技术。

1.2. 内核的优点
很多系统都采用内核,一个显著的特点就是安全性和可靠性。在安全性中有最小特权原
注:) 本文得到国家“863”项目高性能的以太网交换机核心芯片开发的资助,项目主题
为超大规模集成电路重大专项。项目编号是2002BA906A21-08。

深层次的技术竞争体现在核心芯片和操作系统上。为此,863 专家组提出了开发高性能
以太网交换机核心芯片的课题,其目标是研究和开发一款高性能的以太网交换机核心单元,
其水平处于国际前沿,为IT 高技术领域的民族品牌提供支持,对保障我国信息领域的安全


具有重要意义。
则,而操作系统内核具有很大的特权,它可以访问所以主存;它使用固定页面不可被换出;
它的执行不可被中断,不可被抢占。如果使用大内核就会使得许多操作系统功能不必要的拥
有这些特点,使得安全性降低,也使得整个系统的性能下降。

1.3 内核的结构和实现
内核结构技术是把那些最本质,最基本的功能留在内核中,但这个说法本身就很模糊。
也许换个角度就更好理解了:内核与客户/服务器模式是紧密相连的技术。每一个操作系统
功能均以单独的服务器进程形式存在。他与客户的应用进程都存在于内核之外。他们以发消
息的方式通过内核向服务器进程提出服务请求。服务器进程在处理服务请求后,也以发消息
的形式通过内核把结果返回客户进程。所以内核所作的事情就是处理客户与服务器之间的通
讯,检查消息的合法性,并传送他们。实现内核的关键是实现机制和策略分离。他就是把必
须访问硬件和内核数据结构的实现机制放在内核之中,而把实现该功能的算法和策略留给用
户态的服务进程。

第二章:VxWorks 内核

VxWorks 的内核被称作 wind ,包括多任务调度(采用优先级抢占方式),任务间的
同步和进程间通信机制以及中断处理,看门狗和内存管理机制。一个多任务环境允许实时应
用程序以一套独立任务的方式构筑,每个任务拥有独立的执行线程和它自己的一套系统资
源。进程间通信机制使得这些任务的行为同步、协调。

2.1 任务调度
Wind 的多任务的数目并没有明显的限制,总共有256 个优先级。wind 使用中断驱动和
优先级的方式。它缩短了上下文转换的时间开销和中断的时延。在 VxWorks 中,任何例程
都可以被启动为一个单独的任务,拥有它自己的上下文和堆栈。还有一些其它的任务机制可
以使任务挂起、继续、删除、延时或改变优先级。任务调度的系统调用有:建立任务
taskSpawn() ;删除任务taskDelete() ;挂起任务taskSuspend() ;恢复任务taskResume() 等等。

2.2 信号量管理
wind 核提供信号量作为任务间同步和互斥的机制。在 wind 核中有几种类型的信号
量,它们分别针对不同的应用需求:

● 二进制信号量:使用最快捷,最广泛,主要用于同步或互斥。
● 互斥信号量:主要用于优先级继承,安全删除和回溯。
● 计数信号量:用于资源的数目较多的情况。
所有的这些信号量是快速和高效的,它们除了被应用在开发设计过程中外,还被广泛地应用
在 VxWorks 高层应用系统中。信号量的系统调用有:建立二进制信号量:semBCreate(); 
建立互斥信号量:semMcreat() 等等。
2.3 任务间通信
除了信号量机制可用于任务间同步与通信,wind 核还提供了诸如消息队列、管道、等
机制。消息队列是较为复杂的一种通讯机制,它可以使一个任务或者中断服务子程序向另一
个任务发送以指针方式定义的变量。本文将主要讨论消息队列机制,消息队列的系统调用有:
创建消息队列:msgQCreate();删除消息队列:msgQDelete();向消息队列发消息:msgQSend(); 
向消息队列接收消息:msgQReceive() 等等。


2.4 内存管理
在Vxworks 中是使用ANSI C 的函数malloc() 和free()动态的分配和释放内存。但是在嵌
入实时操作系统中调用这两个函数却是危险的,当多次调用它们时,会把原来很大的一块连
续内存区域逐渐分割成许多非常小而彼此不相邻的内存块,即内存碎片。使得程序后来连一
块非常小的连续内存也分配不到。在下文的uc/os-II 操作系统中,我们将看到一种改进的做
法。内存管理的系统调用有:分配一个内存块:malloc() ;释放一个内存块:free()等等。

第三章:uc/os-II 内核

VxWorks 是一个商用的操作系统,他的源码并不公开,为了加深对内核的理解,我选
取了当前得到广泛应用的免费且公开源码的嵌入式操作系统uc/os-II 作为对照。在这两种操
作系统的内核比较过程中学习。

uc/os-II 操作系统本身实际上就是一个内核,其提供任务调度、时间管理、任务间同步
与通信、内存管理和中断服务等功能。他适合小型控制系统,具有执行效率高、占用空间小、
实时性能优良和可扩展性强等特点,最小内核可编译至2k。

3.1 任务调度
uc/os-II 中最多可以支持64 个任务,分别对应优先级0~63 ,其中0 为最高优先级。调
度工作的内容可以分为两部分:最高优先级任务的寻找和任务切换。其最高优先级任务的寻
找是通过建立就绪任务表来实现的。uc/os-II 中的每一个任务都有独立的堆栈空间,并有一
个称为任务控制块TCB(task control block) 的数据结构,其中第一个成员变量就是保存的任务
堆栈指针。在进行任务调度时首先用变量 ostcbhighrdy 记录当前最高级就绪任务的地址,然
后调用os_task_sw() 函数来进行任务切换,这个函数是硬件相关的,它的大部分代码要用汇
编语言完成,其主要功能就是保存现场到TCB 块中,以便以后再次运行。任务调度的系统
调用有:建立任务OSTaskCreat() ;删除任务OSTaskDel() ;挂起任务OSTaskSuspend() ;恢
复任务OSTaskResume() ;等等。

3.2 信号量管理
在uc/os-II 中,建立信号量的函数OSSemCreate() 需要输入一个参数cnt,如果赋值1, 
就相当于二进制信号量,如果赋值n,就可作为计数信号量使用。
很多人对二进制信号量,计数信号量和互斥信号量的区别不太清楚,其实通过看uc/os-II 
的源码,就能很好的理解这种差别。在uc/os-II 中,信号量以及下文中的消息队列的实现都
是通过一个基本的数据结构:事件控制块(ECB)实现的。其成员OSEventType 是一个标志,
记录了这个控制块是用于信号量还是互斥信号量,或其它事件。另一个重要成员是
OSEventCnt ,这三种信号量的区别就主要体现在它的身上,二进制信号量和计数信号量在
实现上并没有什么不同,他们都是通过函数OSSemCreate() 建立的,就是把参数cnt 直接付
给OSEventCnt ,在等待信号量函数中就会递减OSEventCnt ,为0 则把当前任务打标为睡眠
状态,随后执行任务调度函数。

相对而言,互斥信号量就要复杂一些,因为它需要解决处理互斥时出现的优先级反转的
问题。于是就要把没有被占有的,略高于最高优先级任务的优先级,保留给所谓“优先级继
承优先级”(PIP),而这个PIP 就是保存在OSEventCnt 的高8 位的,其低8 位在资源无任务
占用时为0xFF, 有资源占用时为占用它的任务的优先级。在函数等待一个互斥型信号量时,
就会提取PIP 和占用资源的任务的优先级,如果占用资源的任务的优先级比当前任务的优先
级要低(数值大),就需要提升占用资源的任务的优先级为PIP ,从而让占用资源的任务从速
释放资源。建立信号量:OSSemCreate() ;建立互斥信号量:OSSemMCreat() 等等。


3.3 任务间同步与通信
消息队列是uc/os-II中的一种任务间同步与通信机制。因具体的应用有所不同,每个指
针指向的数据结构变量也有所不同。为了使用uc/os-II 的消息队列功能,需要在OS_CFG.H 
文件中,将OS_Q_EN 常数设置为1,并且通过常数OS_MAX_QS 来决定μC/OS-II支持的
最多消息队列数。 

消息队列最根本的部分是一个环形缓冲区,在调用创建消息队列的函数时需要赋给他两
个参数:指向消息数组的指针和数组的大小。例如:void *MymessageQ[SIZE]. 在创建消息
队列完毕时,这个指针数组就被初始化为一个环形的缓冲区,并且返回相应的消息队列的句
柄。任务间同步与通信的系统调用有:创建消息队列:OSMboxCreate() ;删除消息队列:
OSMboxDel() ;向消息队列发消息:OSMboxPost() ;向消息队列接收消息:OSMboxAccept() 
等等。

3.4 内存管理
为了避免内存碎片的问题,uc/os-II 对malloc() 和free()函数做了改进,其基本思想是:
把连续的大块内存按分区来管理。每个分区包含整数个大小相同的内存块,这样,每次分配
和释放的内存块就是固定大小的了。

首先,在OS_CFG.H 文件中有一个开关OS_MEM_QUERY_EN, 决定使用内存管理与否。
然后,使用所谓内存控制块(MCB )的数据结构跟踪每一个内存分区,在MCB 中的成员
OSMemFreeList 把本内存分区中所有可用的内存块链接成一个单向链表。成员
OSMemBlkSize 和OSMemNBlks ,记录内存分区的内存块的大小和数量(他们的乘积当然就
是分配的内存区的大小。) MCB 的初始化工作由建立内存分区的函数OSMemCreate() 来完
成,它的返回值就是一个指向这个MCB 的指针。这样当调用函数OSMemGet() 和OSMemPut() 
分配和释放内存时实际上就是更新由OSMemFreeList 链接的链表。分配内存就是从链表中
取出内存块,释放内存就是把内存块还回链表中。内存管理的系统调用有:建立内存分区:
OSMemCreate() ;分配一个内存块:OSMemGet() ;释放一个内存块:OSMemPut() 等等。

结束语:

与一般的计算机应用相比,嵌入式应用系统往往是要求具有高速处理,配置专一,结构
紧凑和坚固可靠等特点的实时系统,一个正确但迟到的结果同一个错误的结果没有什么本质
不同。更重要的是:嵌入式系统是成本敏感的,能否充分利用现有资源,降低成本对项目本
身常常是决定性的。只有对嵌入式操作系统的内核有深刻的了解,对系统调用函数有充分的
研究,才能开发出稳定,高效的嵌入式系统软件。

参考文献:

【1.】Jean J.Labrosse(邵贝贝译) 《嵌入式实时操作系统uc/os-II(第2 版)》
【2.】王学龙《嵌入式VxWorks 系统开发与应用》
【3.】屠祁,屠立德《操作系统基础》
【4.】李垣陵《UC/OS 和UCLinux 比较》
作者简介:
沈胜庆(1977-),男(汉族),湖北武汉人,武汉邮电科学研究院,硕士研究生,主要研究
方向:IP 技术和嵌入式系统软件。导师:余少华教授,博士生导师。
注:不要稿费。通讯地址:武汉市邮科院路88 号烽火网络有限责任公司。研发部,沈胜庆。
评价:杂志社的审稿非常快,比起其他地方动则3 个月好多了。如果收到投稿邮件就可以自


动回复发稿者就更好了。



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -