静态组件式操作系统设计

dxcnjupt 2007-01-07 01:07:30
简介
组件式OS由不同的组件组装而成,每个组件都必须遵守标准文件所定义的接口,由独立的开发小组进行开发。
操作系统不再是由同一个公司生产销售,而是由不同的公司/组织/个人独立开发的组件拚装而成。
对于普通用户来说,他们可以使用由某个公司发布的已经组装好的操作系统;对于高端用户,黑客,他们可以自由选择需要的组件进行拚装。
如果用现有的商业/技术体系来举例的话,组件式OS的生产销售体系类似与PC机。
PC机的CPU,主办,内存,机箱等不同部分由不同企业设计生产,遵守一定的标准。大部分PC机由PC机销售商组装生产,黑客们则可以购买自己喜欢的部件DIY。
――――――――――――――――――――――――――――――――――――――
应用前景
现在世界上流行的操作系统,包括windows和Linux,有一个最大的特点,它们是由同一个工作组设计的。
随着时代的进步,操作系统代码量越来越大,随之而来的则是开发难度的增大。最终导致了技术门槛提高,升级困难,成本剧增,各种BUG接踵而至。臃肿庞大的开发组的管理也是一个很大的问题。
随着用户需求的增长,现有的操作系统往往只能进行“大众化”设计,针对主要客户群进行设计并对其它客户采取适当的妥协。对于主要客户来说,他们会觉得操作系统里面有很多功能是自己不需要的,而这些功能影响了执行的速度和安全性;对于其它客户来说,现在的操作系统可能根本就不符合他们的需求。
组件式OS设计将解决以上两个问题。
由于组件式OS的各个模块是独立开发,独立调试,独立测试的,所以每个开发小组需要处理的代码可以降至最低。 根据软件工程的原理,独立小组的开发使得开发成本和维护成本成级数下降。 组件式的结构也使得移植和维护变得更加简单,我们没有必要使得一份代码可以在不同硬件上运行,只要提供几份不同的代码就可以了。 组件式开发也可以最大限度的提高全世界开源工作者的工作效率,所有人都可以开放式的参加操作系统的设计和完善工作。
由于可以在安装系统时选择自己需要的模块,不同的用户可以得到不同的操作系统。例如服务器操作系统可以选用带自学习能力的内存管理器,嵌入式操作系统则可以选用非分页内存管理器。数据处理型系统可以省略GDI,而游戏型系统可以采用更好的图形系统。
―――――――――――――――――――――――――――――――――――――――
...全文
302 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
dxcnjupt 2007-01-07
  • 打赏
  • 举报
回复
基本内核组件
基本内核组件包括内存控制,线程进程调度,进程通信。
各组件的基本责任:提供内核调用调用并初始化接口,实现API接口,实现专有功能。
各组件专有功能:
内存控制器:隐藏机器内存控制的细节,使其它组件及用户进程可以透明的使用线性内存。
线程进程调度:使用户进程线程可以透明的共享CPU等硬件软件资源。
进程通信:使各进程之间可以通过消息机制进行通信。至少提供SendMessage, GetMessage两个API调用接口。

内核调用接口:
基本内核组件必须提供标准规定的内核调用函数,并在初始化时将相应的内核调用接口的跳转地址改写为自己提供的函数的地址。
API接口:
基本内核组件必须提供标准规定的API接口函数,通过接受消息或者定义调用门提供接口。除此之外还可通过自定义消息或者自定义调用门(或函数地址,下同)提供更多的功能。
基于技术和商业上的理由,内核接口与API接口的标准暂时无法确定。
如上文所述,组件开发者可以得到几个头文件,但是在基本内核组件装载过程中只能使用已经初始化的组件提供的接口,不得使用未初始化的接口。
装载顺序暂时无法确定。
在保护模式下,基本内核组件和标准组件应共用一个页目录,这样可以高效和安全的进行实现内核调用,而其它组件则无法使用由内核调用组件提供的调用。 如果开启分页机制,则基本内核组件和标准组件的线性地址应该等同于物理地址。
―――――――――――――――――――――――――――――――――――――――
扩展内核组件
扩展内核组件的存在使得非标准定义的组件也能在内核态执行。扩展内核组件不必提供内核调用接口或接收标准信息。 它们可以通过消息机制或者调用门提供自定义的接口。
―――――――――――――――――――――――――――――――――――――――
用户态组件
API接口:API接口是OS与软件开发者之间的接口。
SendMessage与GetMessage以固定的调用门给出,这是最基本的调用接口。
其它API通过dll给出,以屏蔽操作系统的细节。如果有适当理由,也可以仅使用SendMessage和GetMessage工作。
―――――――――――――――――――――――――――――――――――――――
其它组件
这一节描述的是常用的,既可以放在用户态部分,也可以放在扩展内核部分的组件。
文件系统
用户界面
驱动程序
图形设备接口
―――――――――――――――――――――――――――――――――――――――
技术细节
独立调试与独立测试:
设计一些最简单的确认无误的组件,与待调试组件组成操作系统,可以对接口和功能进行调试,若发现错误,则肯定是由于待调试组件的bug造成。
在操作系统中分别装载待测试组件的新旧版本,观察运行结果,可以进行测试。

操作系统的安装:
主要涉及系统描述文件的生成。

组件的硬件层与功能层:
部分组件需要与硬件进行交互,出于开发效率和可移植性的考虑,它们可以被分为硬件层和功能层。
有两种方法可以实现这样的划分。
1在制定标准的时候直接把组件分为硬件层和功能层对待
2在制定标准的时候把组件作为整体对待,组件开发者在开发的过程中可以把组件划分为硬件层和功能层两部分
本文使用后一种方法。

消息中心与线程调度器关于效率的改进:
传统的消息使用while(GetMessage)循环进行控制,若是一个没有得到消息的线程得到了CPU控制,则会导致效率的下降;若是一个高优先级的线程得到紧急消息需要立即执行而又没有得到时间片,则系统的实时性会下降。采用以下方法可以解决这两个问题。
消息直达:对于某些内核级组件,可以设置消息直达,在收到某些消息的时候直接调用线程调度器给出的接口,将CPU控制权转移给该内核组件。
忙时调用:在线程调度器中设置线程属性,当线程消息列表为空时为空闲,该线程不加入调度链表,在收到消息以后将线程设为忙状态并加入调度链表。

认证:
出于安全性考虑,内核态组件应得到受信任组织的认证。
其它组件可视情况进行或不进行认证工作。

附属标准和私有标准:
为达到最大程度的兼容,在基本的标准设定中了只设定了极少的规则。
为了提高可移植性或基于其它理由,可以制定全球统一的“附属标准”或者只有特定行业或几个大型公司遵守的“私有标准”。
初稿成于2006-11-27 南京 d.x.c
我的联系方式email dxcnjupt@126.com, QQ 23559356
已经开发出一个基于intel 16位的标准组件及测试用其它组件
正在开发基于intel 32位保护模式的标准组件。
dxcnjupt 2007-01-07
  • 打赏
  • 举报
回复
组件分解
系统中的组件可以分为标准组件,基本内核组件,扩展内核组件和用户态组件。
标准组件包括装载器,系统描述文件,内核调用接口。
基本内核组件是只有在内核态才能实现的,操作系统必须提供的基本组件,包括内存控制,线程进程调度,进程通信。
扩展内核组件是出于效率,安全或其它原因而放在内核态运行的组件,有可能包文件系统,驱动程序,并行处理,GDI或其它组件。
用户态组件运行在用户态,主要包括API接口。出于安全性考虑,API接口分为特权API与通常API两部分,特权API应该受到特殊保护,不能随意被修改。
―――――――――――――――――――――――――――――――――――――――
标准组件
标准组件是几个特殊的组件,它们是标准的一部分,负责装载和支撑其它组件的运行。不同标准组件采用的策略通常是相似的,设计者与使用者只需要选择可正确执行的标准组件即可。在本文中会给出标准组件的设计方法,但对于其它组件的描述仅限于组件功能,设计者应遵守的规则和可得到的帮助。
标准组件包括装载器,系统描述文件和内核调用接口。

装载器在机器启动,自动跳转7C00后被boot加载并获得控制权。并按以下流程执行装载操作。
首先装载内核调用接口文件,然后是系统描述文件,读之,得到各组件的文件名和装载地址等信息(或基地址,下同),根据该地址装载基本内核组件并调用其初始化程序。内存控制器可以通过移动内存中已装载的组件以及修改内存中的系统描述文件把各组件映射到其它地址。
之后以类似的方法装载其它组件。

系统描述文件:在安装系统的时候生成,根据各组件大小分配装载地址,或者标明“不装载”。这个分配可以被内存控制器改变。

内核调用接口:内核调用接口提供了一个机制,使得各组件可以透明的使用其它组件提供的接口。

技术可行性
一,为了使各内核基本组件能独立运作,我们必须提供独立的逻辑空间。
在IA-32体系中可以用两种方法得到独立逻辑空间,1是使用分段机制,2是提供分页机制。
使用分段机制,需要为每个组件提供一组独立的段描述符和选择子,在切换组件的同时切换选择子,这样每个组件都会认为自己拥有0—Limit大小的独立空间。
使用分页机制,需要为每个组件提供一组独立的页目录和页表,切换组件的同时切换页目录指针,这是目前操作系统中最常用的办法。
对于基本内核组件,考虑到分页机制中组件切换的代价比较大,各组件之间的互相调用也比较困难,我选择分段机制来提供独立逻辑空间。
二,内核调用接口的实现
为了能在各个模块之间实现动态的长跳转,我们产生一个由大量(jmp [Base]:0,nop)单元组成的内存空间,内核组件初始化时对该内存空间进行直接改写,将偏移量设定为指定值。调用的时候先‘一次跳转’到内核调用模块,然后执行‘二次跳转’到达目标代码。
从内核调用的使用者的角度来说,我们提供一个使用者头文件,从头文件中可以得到函数名/函数功能/函数参数/一次跳转地址以及 适当的宏定义。 使用者只要包含了这个头文件,跳转机制实际上是透明的,可以像使用普通函数那样使用内核调用。
从内核调用开发者的角度来说,他们可以包含一个针对特定组件的头文件,例如内存模块的设计者可以包含一个内存开发者头文件。在这些头文件中声明了一系列SetXXXCall函数,其中XXX表示该模块必须实现的内核调用函数,只要通过参数传入适当的地址,调用SetXXXXCall即可完成调用设定。
―――――――――――――――――――――――――――――――――――――――

23,216

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧