分类:
2009-12-24 13:33:57
前言及绪论 |
级别: 初级 汤海京 (), 软件事业部工程师, 联想集团有限公司 2001 年 8 月 01 日 《基于面向对象操 作系统开发平台(OSKit)的分析与程序设计》是我们奉献给读者的一个新专栏。本专栏的作者汤海京将向大家系统地介绍OSKit的线程机制,主要论述了 三大部分内容,它们是:线程通讯,线程初始化和线程调度。希望读者能在最短的时间内了解OSKit。本文是第一篇《前言及绪论》。 如果说自由软件的出现是一个偶然的话,那么,席卷全球的Linux热潮则是一个奇迹,它正以势不可挡的趋势迅猛发展,其前途不可限量。 Linux内核源代码的开放给希望深入操作系统内部世界的人们提供了可能,但随之而来的问题是,当我们要开发自己的操作系统时,由谁来读系统的 kernel部分呢。对这部分的处理从逻辑上分析不外乎三种方式:全部保留、对其进行裁减、全部推倒重来。很显然,最后一种方法是不可能的,而如果我们采 用的是第一种方法,其结果当然一定可以满足我们的要求,但是,最后编译出来的核心将十分的庞大,尤其是对嵌入式操作系统的开发者来说,是不能忍受的,所 以,大多数开发者采用的第二条路。 但是,第二条路也非平坦的大道,道理很简单,你要想对kernel进行裁减,首先你应该将全部的源代码阅读一遍,并且将其中的相关性理顺,然后才能谈到裁减,所以工作量也十分的庞大。 然而,OSKit的出现改变了这一切,它使得我们不需要将精力集中在kernel源代码的阅读上,因为kernel部分的源程序已经由OSKit的开发人员替你分析过了,他们将源码全部模块化,并将所有模块之间的相关性写在了文档之中,呈现在你的面前,这与你自己分析源代码的结果是一样的。 OSKit最本质的东西和Linux一样,体现在"自由"和"开放"的思想,"自由"意味着世界范围内的知识共享,由于OSKit出现在Linux之后, 其设计思想继承了Linux的精髓,所以说它的出现并不完全是美国犹它大学计算机科学系FLUX研究组的功劳,而应该是"自由"的结果。"开放"则意味着 OSKit对所有的人都敞开大门,在这种开放而自由的天地里,你可以中分发挥自己的创造才能。
OSKit 是由美国犹它大学计算机科学系FLUX研究组编写的一套模块化部件和库函数,用于架构操作系统内核、服务器以及其他的OS级软件。我们设想一下,在一个操 作系统的研发项目中,底层模块的开发工作会占去大部分时间,并耗费掉开发人员的大部分精力。而OSKit的出现恰恰弥补了这个缺陷,其设计意图是提供一套 可重用的模块,让使用者避开复杂的底层,把精力集中在他们感兴趣的问题上,也就是说,当开发人员拿到OSKit之后,便立刻拥有了一个完整而且安全的核 心,使他们可以集中精力研发操作系统的高层次问题,如作业控制、虚存、IPC、文件系统、系统安全以及高级语言(如Java、Lisp或ML)等。这样可 以大大丰富操作系统的应用层,为用户提供更多更好的服务,提高操作系统的运行效率,增强操作系统的安全性和稳定性,从而使你的操作系统更加具有魅力。 对于站在操作系统技术最前沿的多线程编程和成熟的作业控制系统,以及时下最流行的嵌入式操作系统,OSKit都提供了支持。通过对美国犹它大学计算机科学 系FLUX研究组网站的追踪,我们注意到OSKit的版本大约每三个月就更新一次,而且在每次发布的版本里都有许多新的算法公布,还有许多老版本中的 BUG被修改;这说明OSKit不但一直处于操作系统开发平台的最前沿,而且其自身也在不断的完善。 通过对OSKit深入细致的分析与研究,我们发现犹他大学的开发人员们从一开始就确定了自己的目标,那就是对OSKit进行模块化,仿佛Windows中 的动态连接库一样,让后来者即使不使用OSKit中的某一部分,仍然可以使用其余部分来完成他们的目标。这样的设计思路十分灵活,为开发者和使用者都提供 了便利。 当我们从犹他大学得到OSkit的2000年五月版时,它是个压缩包,使用tar在linux下解开后,就得到了源码,这需要我们在linux下重新编译。 目前,编译OSKit需要以下的工具:GNU make、GNU CC (gcc) 2.95.2版。 注意:Redhat Linux 6.2中的GCC并不是2.95.2,如果要成功编译OSKit,需要先将我们的GCC升级。当然,如果你使用的是Turbo linux 6.0的话,它提供的就是GCC 2.95.2。 在开始编译OSKit之前,我们必须注意一点,那就是要对源码进行一点改动,让它支持实时操作,即将 /oskit20000505/threads/MakeFlage 中的: # OSKIT_CFLAGS + = -DPTHREAD_SCHED_EDF -DPTHREAD_REALTIME 中的注释符号 # 去掉。
由于我们的环境是Linux,所以论文中的根目录用"/"表示,而不是Windows中的"\"。由于我们是在intel
586上编译,而我们的目标机要支持到intel
386,所以我们应该在OSKit的目录下键入:
一开始,为了能让大家尽快熟悉OSKit,犹他大学的研发人员们给出了许多很具代表性的例子供使用者进行试验,我们也编写了一个小型的操作系统,供学习研究之用。 OSKit中库的设计是很经典的,开发者们花费了大量时间清楚地标出了每个库与其它库的依赖关系,这使得OSKit不但保留了操作系统的原汁原味,而且还 把库之间的相关性降低到了最低限度,使得使用者可以随意增减其中的库函数。实际上,在很多情况下,特别是在某些函数库中,为了有效的使用OSKit,必须 替换掉其中的一些函数或符号,以适应我们的执行环境。要重载某个库中的函数或者符号,只要在你的核心或应用程序中再定义一遍就可以了,LINK程序会确保 去使用你所定义的函数和符号。由于在Linux下的编译器是靠读取Makefile文件来确定编译连接的对象以及规则,所以我们认为直接修改Makefile文件要比修改OSKit源码更加方便而且安全,这与Windows下的工程文件十分相似。 如果使用OSKit所提供的模块化部件和库函数编写出了自己的操作系统核心代码,并且对在LINUX下用GCC编译源码有所了解的话,就可以借助OSKit为使用者提供的一整套核心制作命令和LINUX提供的GCC来生成自己的核心文件zImage,然后使用LINUX命令DD将核心写入一张1.44MB的软盘,重新启动计算机,从软盘引导就可进入我们自己编写的操作系统了。 另外,考虑到用户环境复杂多样的实际情况,OSKit还提供了对许多种操作系统的支持,包括Linux、Mach 、BSD或者MS-DOS,当我们用GCC将源码编 译成"filename.o"的格式之后,使用OSKit提供的不同的核心制作命令来生成不同操作系统下的核心,其具体实现是由mkbsdimage、 mklinuximage和mkdosimage来完成的。这些脚本在OSKit的安装和配置阶段会根据你指定的环境自动安装完毕。在每一个脚本运行的时 候都有各自不同的参数。 OSKit所提供的功能被分成三类: 接口、 函数库和 部件库
1.4.1 接口
1.4.2 函数库
1.4.3 部件库
1.4.4 执行环境
纯执行模块: 这是OSKit执行环境中最简单的一个模块,这些部件或函数中没有全局变量或静态变量,只使用和处理由目标环境传递来的数据。例如函数strlen,它只 通过目标环境传递给它的字符串指针求出字符串的长度,并将其返回,它只接触参数数据域,而不影响目标环境。当这些函数使用的数据集是分离的,它们可以安全 地同时被调用,而不需要同步,反之则不行。例如对重叠的目标缓冲区并发使用memcpy调用时不安全的。 非纯执行模块: 这些模块中使用了全局变量或有可能改变全局共享状态,例如liboskit_kern(核心支持库)中的许多函数建立和访问全局处理器寄存器和数据结构, 因此它们是非纯执行模块。非纯执行模块有以下特点:非纯函数和部件可能依赖于全局状态,如全局变量,静态变量,处理器中的特殊寄存器等。除非有明确的声 明,非纯函数和部件是不可重入的,并且运用在多线程系统中也是不安全的。为了在一个多线程/多处理器环境中使用这些函数和部件,目标操作系统必须提供适当 的同步代码。 阻塞模块:它扩展了非纯模块来支持非抢先的多线程,这些模块中有一类可重入的函数称为阻塞函数,在这模块中,除非明确声明为非阻塞函数,否则函数是阻塞的。为了在一个完全抢先的、可中断的或者多处理器的环境中使用阻塞模块,必须在进入模块前加锁,在退出模块时将锁释放。 可中断阻塞模块:在它之中每个部件都是一个单线程的执行域,在一个给定的时刻,只有一个(虚拟的或者物理的)CPU可以执行部件中的代码。例如:在一个多处理器系统中,在进程级别下,任意时刻在一个部件集内只有一个CPU被允许执行;这能够通过在部件前后放置全局锁来实现。 在一段时间内,部件中可以存在多个活动进程,但在某时刻只有一个进程被执行。目标操作系统给每个活动进程提供一个独立堆栈,这个堆栈在阻塞函数运行时被保 留。只有在操作完成后,对部件的调用返回时才放弃该堆栈。部件中的代码总是运行在两个级别中之一,进程级或中断级。有意思的是一些部件的函数和方法只能在 进程级别被调用,而另一些只能在中断级别被调用,还有的能在任何级别被调用。调用的细节属于接口描述的一部分。 部件中无论进程级别或中断级别的操作都能被部件中的中断处理程序中断,除非代码调用osenv_intr_disable屏蔽了中断。当部件在进程级运行 时,OSKIT假定中断开放,部件在处理过程中可能临时屏蔽掉中断,但必须在返回到目标操作系统前重新激活。同样,当部件在中断级运行时,OSKIT假定 中断被屏蔽,但是部件可以在目标操作系统允许其它中断级别的活动中断该部件时重新激活中断。 当目标操作系统在一个部件内中断一个进程级别的活动时,在继续这个活动前,操作系统必须执行完这个中断级别的活动。同理,若一个中断级的活动被中断,那么 最近的中断级别的活动必须在继续前一个中断级别的活动之前完成。部件中运行在中断级别的代码不能调用目标操作系统提供的阻塞回调函数;只有非阻塞的回调函 数能够在中断级别被调用。
|