Embedded System Design
---- Embedded OS
Zhaofeng
SJTU-SoME2007-11-02
OUTLINE
• UNIX/Linux 发展历程• POSIX
• System Call
• 嵌入式操作系统的基本概念
UNIX 发展历程• 美国 AT&T (美国电话电报)公司的贝尔实验室
于 1969 年在 DEC 的小型机 PDP-7 上开发成功• 1973 年开发 C 语言并改写 UNIX 第 3 版• 1974 年 7 月,” UNIX 分时系统”一文在美国权
威杂志 CACM 上发表• 最早可获得的 UNIX 是 75 年的 UNIX 第 6 版• 1978 年的 UNIX 第 7 版,是当今 UNIX 的祖先• 1983 年 AT&T 公司公布了 UNIX System V 。
• 1968 ~ 1970– 贝尔实验室的 Ken Thompson 和 Dennis Ritchi
e 和 Joseph Ossanna 在开发 MULTICS(MULTiplexed Information and Computing System时 ) 遇到了失败,同时产生的副产品被戏称为UNICS(UNiplexed Information and Computing System) ,然后又逐渐演变为 UNIX 。
– PDP-7 上汇编语言开发的单用户操作系统– PDP-11 上 C 语言开发
Ken Thompson
Dennis Ritchic
• Dennis M.Ritchic 是朗讯科技公司研发机构贝尔实验室计算机科学研究中心系统软件研究部主任,获得哈佛大学学士、硕士学位后,他于 1968 年加入贝尔实验室。
• Dennis M.Ritchic 协助 Ken Thompson 创建了 UNIX 操作系统。他是 C 语言的主要设计者。目前,他仍然致力于操作系统和语言的研究工作。
BSD UNIX• 由大学开发的非 AT&T 系统 UNIX 是 Berkel
ey 分校( CSRG )运行在 VAX-11 机上的 UNIX BSD
• 最著名的是 4.1BSD 、 4.2BSD 、 4.3BSD和 4.4BSD ,这些版本中加入页式虚存、长文件名、 网络协议 TCP/IP 等,在 UNIX 发展中起了重要作用,已成为教学、科研、商用的主流系统。
UNIX 主要变种AT&T
第 1---第 7版( 71---78年)
SYSTEM III---V
( 82、 83年)SVR2---SVR4
( 84---89年)
Berkeley分校1BSD—4BSD
( 78—80年)4.0SBD—4.4SBD
( 80—93年)
1989年: AT&T 与 Berkeley分校两个分支的 UNI
X会合并且统一为 SVR4
源代码版本的 UNIX
• Minix– 由 Andrew Tanenbaum 实现。是一个教学用的系
统。在很多应用平台上都有相应的版本。• 386BSD
– 由 Bill 和 Lynne Jolitz 维护。• FreeBSD• NetNSD• Linux
– 由芬兰的 Linus B. Torvalds 开发,是目前最流行的免费 UNIX 系统。有望取代 MS Windows 成为 PC的主流操作系统。
教堂与集市
• Cathedral :别忘了 windows– 源代码锁定在有限范围内– 新版本的发行由市场决定
• Bazaar :– 征集并充分利用早期的反馈– 巨大数量的脑力资源进行平衡配置– 开发理想的操作系统– 享受工作的快乐,获得充分的自豪感
http://www.firstmonday.org/issues/issue3_3/raymond/#d4
有序的 Linux 开发• Linux 采用了双树结构
– Stable tree– Development tree(Unstable tree)
• 源代码版本号: x.y.z– 2.3.12– 2.4.0
http://www.kernel.org
OUTLINE
• UNIX/Linux 发展历程• POSIX
• System Call
• 嵌入式操作系统的由来与特点• 嵌入式操作系统的基本概念
POSIX标准• POSIX 标准: 1990 年, IEEE 拟定了一个 UNIX 标准,称作
POSIX 。它定义了相互兼容的 UNIX 系统必须支持的最少系统调用接口。该标准已被多数 UNIX 支持,同时,其他一些操作系统也在支持 POSIX 标准。
• POSIX ( Portable Operating System Interface ):
可移植操作系统接口,是操作系统的国际标准接口。
• POSIX对 Linux 的发展起了极大的作用
OUTLINE
• UNIX/Linux 发展历程• POSIX
• System Call
• 嵌入式操作系统的由来与特点• 嵌入式操作系统的基本概念
“Core” KernelApplications
System Libraries (libc)
System Call Interface
Hardware
Architecture-Dependent Code
I/O Related Process RelatedScheduler
Memory Management
IPC
File Systems
Networking
Device Drivers
Mod
ules
System Call( 系统调用 )
• 用户程序用以请求内核提供的服务的特殊函数• 除非一个汇编程序仅仅进行数学运算,否则其必
须进行输入输出及退出等操作,而要进行这些操作就需要调用操作系统的服务。
• 在 UNIX 系统下有两种方式实现对系统调用的使用:通过经过封装的 C库 (libc)或者直接调用
• 其功能和性能很大程度上反映了操作系统的功能和性能
常用的系统调用
分为 I/O处理、进程、时间、内存等 1 、文件操作 2 、进程控制 3 、信号处理 4 、高级 I/O 5 、网络通信 …
除特殊说明,所有函数返回负值表示失败。
进程相关的系统调用函数• fork()• clone(), pthead_create()• exit()• wait()• pipe()• signal()• kill()• exec()
OUTLINE
• UNIX/Linux 发展历程• POSIX
• System Call
• 嵌入式操作系统的基本概念
任务• 一个任务,也称作一个线程,是一个简单的程序,该任务可以认为 CPU完全只属该任务自己。实时应用程序的设计过程,包括如何把问题分割成多个任务,每个任务都是整个应用的某一部分,每个任务被赋予一定的优先级,有它自己的一套 CPU寄存器和自己的栈空间。
StackStackStackStack
StackStack
StatusSP
Priority
StatusSP
Priority
StatusSP
Priority
StatusSP
Priority
StatusSP
Priority
StatusSP
Priority
SPSP
Memory CPU
TASK 1 TASK 2 TASK n
CPU Registers
多任务
……
多任务• 多任务运行的实现实际上是靠 CPU( 中央处理单元 ) 在许多任务之间转换、调度。 CPU只有一个,轮番服务于一系列任务中的某一个。
• 多任务运行使 CPU 的利用率得到最大的发挥,并使应用程序模块化。在实时应用中,多任务化的最大特点是,开发人员可以将很复杂的应用程序层次化。
资源与共享• 任何为任务所占用的实体都可称为资源。
资源可以是输入输出设备,例如打印机、键盘、显示器,资源也可以是一个变量,一个结构或一个数组等。
• 可以被一个以上任务使用的资源叫做共享资源。为了防止数据被破坏,每个任务在与共享资源打交道时,必须独占该资源。
任务的状态• 休眠态相当于该任务驻留在内存中,但并不被内核所调度。
• 就绪意味着该任务已经准备好,可以运行了,但由于该任务的优先级比正在运行的任务的优先级低,还暂时不能运行。
• 运行态的任务是指该任务掌握了 CPU 的控制权,正在运行中。
• 挂起状态也可以叫做等待 (WAITING)事件态,指该任务在等待,等待某一事件的发生,(例如等待某外设的 I/O 操作,等待某共享资源由暂不能使用变成能使用,等待定时脉冲的到来或等待超时信号的到来以结束目前的等待,等等)。
• 发生中断时, CPU 提供相应的中断服务,原来正在运行的任务暂不能运行,就进入了中断状态。
挂起
休眠
就绪
运行
中断
任务切换• 任务切换 (Context Switch or Task Switch)• 当多任务内核决定运行另外的任务时,它保存正在运行任务的当前状态( Context ),即 CPU寄存器中的全部内容。这些内容保存在任务的当前状况保存区( Task’s Context Storage area ),也就是任务自己的栈区之中。入栈工作完成以后,就是把下一个将要运行的任务的当前状况从该任务的栈中重新装入 CPU 的寄存器,并开始下一个任务的运行。这个过程叫做任务切换。
• 任务切换过程增加了应用程序的额外负荷。 CPU 的内部寄存器越多,额外负荷就越重。做任务切换所需要的时间取决于 CPU 有多少寄存器要入栈。
• 老板※行政※教师※工程师※ Task Graph
内核( Kernel )• 多任务系统中,内核负责管理各个任务,或者说为每个任务分配 CPU 时间,并且负责任务之间的通讯。
• 内核提供的基本服务是任务切换。之所以使用实时内核可以大大简化应用系统的设计,是因为实时内核允许将应用分成若干个任务,由实时内核来管理它们。
• 内核本身也增加了应用程序的额外负荷,代码空间增加 ROM 的用量,内核本身的数据结构增加了 RAM 的用量。但更主要的是,每个任务要有自己的栈空间,这一块吃起内存来是相当厉害的。
• 内核本身对 CPU 的占用时间一般在 2 到 5 个百分点之间。 • 单片机一般不能运行实时内核,因为单片机的 RAM 很有限。通过提供必不可缺少 的系统服务,诸如信号量管理,邮箱、消息队列、延时等,实时内核使得 CPU 的利用更为有效。
调度 (Scheduler)
• 调度就是要决定该轮到哪个任务运行了。• 多数实时内核是基于优先级调度法的。每个任务根据其重要程度的不同被赋予一定的优先级。
• 基于优先级的调度法,指 CPU总是让处在就绪态的优先级最高的任务先运行。
• 究竟何时让高优先级任务掌握 CPU 的使用权,有两种不同的情况 :– 不可剥夺型内核– 可剥夺型内核。
不可剥夺型内核• 不可剥夺型内核(或非抢占式内核, Non-Pr
eemptive Kernel )•不可剥夺型内核要求每个任务自我放弃 CPU
的所有权。•不可剥夺型调度法也称作合作型多任务,各
个任务彼此合作共享一个 CPU 。•异步事件还是由中断服务来处理。中断服务
可以使一个高优先级的任务由挂起状态变为就绪状态。但中断服务以后控制权还是回到原来被中断了的那个任务,直到该任务主动放弃 CPU 的使用权时,那个高优先级的任务才能获得 CPU 的使用权。
低优先级任务
ISR
低优先级任务
高优先级任务
任务正在运行
中断到来 , 中断原来任务执行中断服务子程序 ,使一个 高优先级任务进入就绪状态 由于是不可剥夺型内核,低优 先级任务未执行完毕,高优 先级任务不能立即执行中断返回继续执行原来任务
任务执行完毕 ,控制权交给 高优先级、已就绪任务高优先级任务开始执行
不可剥夺型内核运行原理不可剥夺型内核运行原理
不可剥夺型内核缺点• 不可剥夺型内核的最大缺陷在于其响应时间。高优先级的任务已经进入就绪态,但还不能运行,也许要等很长时间,直到当前运行着的任务释放CPU 。
• 不可剥夺型内核的任务级响应时间是不确定的,不知道什么时候最高优先级的任务才能拿到 CPU的控制权,完全取决于应用程序什么时候释放 CPU 。
可剥夺型内核
• 当系统响应时间很重要时,要使用可剥夺型内核(或抢占式内核, Preemptive Kernel )。
• 最高优先级的任务一旦就绪,总能得到 CPU 的控制权。
• 当一个运行着的任务使一个比它优先级高的任务进入了就绪态,当前任务的 CPU使用权就被剥夺了,或者说被挂起了,那个高优先级的任务立刻得到了 CPU 的控制权。
• 如果是中断服务子程序使一个高优先级的任务进入就绪态,中断完成时,中断了的任务被挂起,优先级高的那个任务开始运行。
可剥夺型内核运行原理
低优先级任务
ISR
高优先级任务
低优先级任务
低优先级任务正在运行
中断到来,中断当前任务
中断服务完成,退出中断 进入新的优先级更高的任务新任务执行
新任务执行完毕, 控制权还给原来的任务
继续执行原来的任务
执行中断服务,把另一个任务 置为高优先级、就绪状态
可剥夺型内核• 使用可剥夺型内核,最高优先级的任务什么时候可以执行,可以得到 CPU 的控制权是可知的。
• 使用可剥夺型内核使得任务级响应时间得以最优化。
• 使用可剥夺型内核时,应用程序不应直接使用不可重入型函数。调用不可重入型函数时,要满足互斥条件,这一点可以用互斥型信号量来实现。如果调用不可重入型函数时,低优先级的任务 CPU 的使用权被高优先级任务剥夺,不可重入型函数中数据有可能被破坏。
可重入性 (Reentrancy)
•可重入型函数可以被一个以上的任务调用而不必担心数据的破坏。
•可重入型函数任何时候都可以被中断,一段时间以后又可以运行,而相应数据不会丢失。
•可重入型函数只使用局部变量,即变量保存在 CPU寄存器中或堆栈中。如使用全局变量,则要对全局变量予以保护。
可重入型函数
void strcpy(char *dest, char *src)
{
while (*dest++ = *src++) { ;
}
*dest = NUL;
}
函数 strcpy ()做字符串的复制。因为参数保存在堆栈中,故函数可以被多个任务调用,不必担心各任务调用函数期间会破坏对方的指针。
任务调度策略-抢占方式
高优先级任务 A
中优先级任务 B
低优先级任务 C
Event Event
Pre_empty: 不同优先级的任务采用抢占方式
任务调度策略-时间片轮转方式
A
B
C
D
A
B
C
D
时间片
Timeslice: 相同优先级的任务采用时间片轮转方式
任务优先级 • 每个任务都有其优先级。任务越重要,赋予的优先级应越高。 –静态优先级
• 应用程序执行过程中诸任务优先级不变,则称之为静态优先级。在静态优先级系统中,诸任务以及它们的时间约束在程序编译时是已知的。
–动态优先级 • 应用程序执行过程中,任务的优先级是可变的,则
称之为动态优先级。实时内核用之避免出现优先级反转问题。
任务优先级举例
ISR space
system task
user task
IDLE
优先级
task space 230
255
0
优先级翻转与优先级继承• 如果完全按照优先级来进行任务调度,则会发生如下情况:
–低优先级任务 TaskB首先运行,调用 semTake() 获得资源;
–高优先级任务 TaskA就绪运行,调用 semTake()申请资源,被阻塞;
–只有当 taskB 调用 semGive()释放资源后, taskA才能继续运行
解决方法• Priority inheritance protocol (优先级继承
协议)–让低优先级任务提高任务优先级,提高到和被阻塞高优先级任务同样的级别。
• Priority ceiling protocol (优先级限高协议) .– 低优先级任务这次不是获得高优先级相同的优
先级,而是获得某个预先设置好的优先级。而这个预先设置好优先级肯定不会比当前所有的存在的优先级低。在实现中,这个优先级一般被设置为实时系统中最高可能的优先级。