LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1668|回复: 0

移植BSD UNIX到新平台--基于移植NetBSD到Macintosh的经历

[复制链接]
发表于 2008-5-24 17:56:42 | 显示全部楼层 |阅读模式
本文是这篇文章的翻译:http://www.teamten.com/lawrence/291.paper/291.paper.html
Lawrence Kesteloot
1995年1月20号
译者:不开花
1介绍

伯克利軟件發布(BSD) UNIX的源码可自由使用。本文给对于想移植这个系统到新架构的人做个指南。做移植很可能需要给新机器编写设备驱动,如果BSD UNIX还没移植到目标CPU的话,你甚至还需要重写操作系统汇编语言部分。这个指南将讨论如何开始移植,需要修改什么文件,需要编写什么驱动,以及当发布所移植的系统供公众使用的流程。

假定读者(以及任何参与移植的人)通晓C,能熟练使用UNIX,并至少学过大学操作系统课程。
1.1UNIX和BSD简史
UNIX在1970年前期[1]由贝尔实验室(AT&T)开发。一些大学买下了附带许可证的源码,加利福尼亚大学伯克利分校从1979年到1994年[3]重写和增强了系统的很多部分。他们最终发布了BSD版UNIX,但是部分源码仍受AT&T版权所限制。BSD用户必须用不菲代价从AT&T购买源码许可。

在1991年,伯克利的计算机科学研究组(CSRG)移除了4.3BSD里由AT&T所写的部分并把其余的以伯克利网络版2发布(Net/2)。Bill和Lynne Jolitz重写了缺失的部分,完成了Net/2到i386移植的大部分,并发布了386BSD 0.0。随即发布了一个bug稍少的386BSD 0.1,不断拖延并有很多bug的0.2版导致一些小组开始了他们自己的BSD发行版本。FreeBSD小组以386BSD为基础,添加了一些增强,为常见的IBM PC系列机器发行BSD。NetBSD组决定发布386BSD的研究版本,他们现在已经移植到超过半打的机器。NetBSD系统最适合于处理不同架构在此推荐基于NetBSD源码的移植。作者和四个别的同学(Brad Grantham, Allen Briggs, Mike Finch, and Chris Caputo)移植了NetBSD到苹果机Macintosh上,那个移植已经作为NetBSD标准套件的一部分。
1.2项目摘要

移植BSD包含如下步骤。你需要
◆浏览现存的NetBSD移植,找到一个和你要移植到的机器相近的那个(2.1节);
◆写个用于测试设备驱动和引导器的单独内核(2.3节);
◆修改或重写汇编语言部分(3.1节);
◆完成基本设备驱动和机器相关代码(第4章);
◆把你的修改纳入NetBSD(5.6节)。


最后你可能想把你的移植发布给公众使用,这包括制作二进制发行套件和一些安装工具,还要个邮件列表,FAQ,和相当的耐心(第5章)。
1.3术语

这里定义一些术语以免随后出现混淆。内核是一块在UNIX运行时总是驻留的一块代码并作为硬件和像CPU,内存,磁盘等资源管理的接口。用户程序(在BSD圈子里通常称为user-land)是除了内核之外的任何程序;即,用户可调用的所有程序。这包括像ls和cc这样的,还有像inetd和timed这样的守护程序。

部分内核是机器不相关的代码,部分是机器相关的代码。前者在各个移植间共享,后者对于每个移植是不同的。有些代码是这两者的混合体,例如Motorola 68000系列代码仅在一些移植间共享。

内存管理单元(MMU)是虚地址到物理内存地址转换并在进程空间间负责处理保护的硬件。有时候MMU是个位于CPU和内存间的单独芯片,有时候直接集成在CPU里。内存里有MMU表指示MMU映射。

有两类内存地址。物理地址用于直接访问内存;即,它是访问数据时送到RAM的地址。虚拟地址首先经过MMU并被转换到(通常是不同的)物理地址。如果虚地址不相应于物理地址或如果不允许在那个内存段这么操作(例如,写到那些只读映射内存),那么MMU缺失,导致内核从磁盘取页,装入一个新的,或是终止导致缺失的程序。

任何可执行的二进制程序(包括内核用户程序)有三部分:文本段,数据段,和bss段。文本段是机器码并通常映射为只读,因此MMU得到不定的写指针。bss(Block Started by Symbol,译者注:源自IBM7094汇编指示符)不保存在磁盘上并表示程序未初始化的全局变量。在UNIX里,当加载程序时,会分配用于bss段的空间并初始化为零,UNIX的这一行为不大可能改变,否则大多数程序都无法工作了。提醒一下,一些别的操作系统(例如,MS-DOS)并不清除bss,并在程序启动时假设它的内容,这使得程序没有可移植性。
1.4资源
NetBSD内核大约有150,000行代码,这可能有点使人敬而远之。大多数尝试驾驭内核的人会对它的巨大和复杂性都有挫折感。画个内核的图示或写出启动顺序可以帮助从大局上把握内核所做的工作。这对于内核的汇编部分特别有用,例如,初始化多少内存不大可能很明显。当阅读内核代码时,使用编辑器跳到一个标识的定义处是很有用的。Ctags程序可以用于这个用途。

当前大约一打人正在移植NetBSD到各种机器,当你进行不下去时,用到他们是很重要的。这是因为他们可能有知道你的问题的答案还可能是你的方法不对。可通过邮件core@NetBSD.ORG来联系NetBSD的四个核心成员。可通过alice@acm.vt.edu来联系移植NetBSD到MACintosh的团队成员。
2项目自举

引导自举这个术语源于阻止你从解靴帶停下来的想法并表示不需要基础就能启动一些事情的进程。
自举引导东西是个有趣的任务,很明显,因为几乎不需要任何东西或无论如何不足以直接得到最终期望的结果就能启动;所构建的基础必须递增。自举引导一个BSD移植所用的步骤摘要于本节。
2.1选择起始点

从头编写所有机器相关的代码是不实际的。你应该使用和要移植到的目标机器类似的NetBSD移植作为基础。对于目标机器的CPU,已经有到其上的移植是理想的情况;这会减少你重写机器相关部分所有机器语言部分的麻烦。最易于移植到其上的CPU是摩托罗拉从69020开始的68000系列。对于这个芯片已经有几个移植了(例如,MACintosh,Sun3,Amiga,和HP300),并有少量代码在它们之间共享。还支持Intel i386,MIPS R3000(它的移植名是“PMAX”),还有Sun的Sparc芯片。发送邮件到core@NetBSD.ORG获取最新列表和正在进行的移植。

给你的移植取个尽可能和要在其上运行的机器相关的名字。例如,我们的Macintosh移植最初称为“Mac”,但随后改为“Mac68k”,因为不支持PowerPC芯片。创建/usr/src/sys/arch/name 子树(这里name是你的移植所选的名字),重命名相应的子目录和文件,你可以开始移植了。
2.2交叉开发环境

当准备好移植并开始后,需要在BSD里编译内核。此时需要在别的UNIX平台上设置交叉编译环境。选择和目标机器及BSD类似的机器和操作系统是很重要的,这样可避免像不同CPU尾端(字内的字节顺序),头文件差异(例如,ctype.h里的宏实现通常是不同的),目标文件格式不同等问题。
NetBSD项目是用了一个叫做pmake的增强的make。它允许makefile包含别的makefile,这是系统频繁用到的一个特征。这是系统中唯一可用用通常make编译的程序,因此应首先编译它。随后要编译的工具是:gcc,as,ld,ar,ranlib和size。

编译开发工具时一个可能的问题是BSD源码可能会用到本地的头文件和库。这不仅导致编译错误,这种情况下,本地头文件会取代一些BSD的头文件,但是一些库运行时可能有不同的行为或实现。例如,chmod()不是像BSD期望的那样,而是调用我们的交叉开发平台解释它的参数,导致BSD连接器产生的所有文件只有执行权限而不是读和写权限。

由于UNIX可能已有上面所提名字的用于交叉开发的工具,写个允许你在本地和BSD可执行程序件选择的脚本是很有用的。这个脚本应当在本地和BSD头文件和库件选择。作为替代方案,可以重命名BSD实用程序和makefile并相应更改路径。
2.3能独立运行的内核

操作系统可以一两种方式引导。在一些架构上(例如,HP300),引导机器致使ROM执行一些侦测,读取磁盘的第一块到内存并执行。第一块通常读取包含能独立运行内核的接着的8块并执行。可独立运行的内核除了从主文件系统读取文件和能从网络引导外能做的事很少。内核要从某个特定分区(引导分区)的目录结构搜寻一个预先定义名称的文件,例如,unix,vmunix,或netbsd,并把它加载到内存,清除bss,并执行它。在别的架构(例如, Macintosh),以MacOS为例,不用内核,它的函数放到了引导器里了(参阅2.4节)。

在别的情况下,独立运行内核是个测试设备驱动和别的没有中断接口,内存映射或内核其余部分的实验性代码的地方。在Macintosh移植过程中,在和内核代码连接前,我们编写和测试了显示,串口,键盘,时钟和磁盘驱动。我们还测试了MMU映射和中断行为。能独立运行内核的另一个优点是比UNIX内核小的多,编译的更快,加快了开发周期。

2.4引导器

一些移植(例如,Macintosh)直接从本地操作系统引导。以Macintosh为例,这比开机直接引导稍慢一些,但是允许引导器传递一些关于机器从MacOS获得的信息。(例如,显存大小)。引导器要做这些事情:

1.给出一个磁盘和分区数,从上面找到根目录和内核;

2.加载内核(文本段和数据段)到连续分配的空间;并

3.在内核后复制例程代码并执行例程。

例程必须禁止中断,复制内核代码段和数据段到内存0地址位置处,为bss段清除足够的空间,并跳转到内核的起始位置。例程要注意在清除bss时候不要把自己清除了。这可通过写例程使其在内存高位以使它的位置至少是内核代码,数据和bss的和。

引导器也负责传递信息到内核。如果信息量很小(例如debug模式),这可通过寄存器来做。如果要传递的狠多,例如所日期和时间,视频地址和模式或机器配置信息等,可通过精心的组织(例如文本变量数组)。

3机器相关代码

内核分为两个主要部分:机器不相关代码和机器相关代码。前者在各个移植间共享,全由C写成,并包含不依赖于内核所运行架构的算法和数据结构。后者包含由机器不相关部分所调用的例程和模块。内核的汇编部分存在于一个文件里,locore.s。pmap.c文件是内核的机器不相关虚存代码和机器的内存映射设备的接口。最后,各种机器相关的代码放在machdep.c文件里。

3.1locore.s

locore.s文件包含用于移植的所有的汇编语言代码。包含中断和异常处理,自举代码,任务切换代码,和一些小的和频繁使用并应该用汇编编写的例程(例如,用于复制内存块的例程)。应该尽可能少的使用汇编,因为这不可移植也不易于维护。一些移植把部分locore.s的内容放到locore.c。

locore的目标文件首先连接到内核执行并通常包含中断向量表。locore里向量入口的存根清除堆栈并调用C例程来合理的处理中断和陷入。汇编语言可能也要决定中断情况,这跟架构是相关的。例如,由内核或用户代码和访问交换出去的页面或无效位置造成的页缺失将产生不同的动作。

引导器或可独立运行的内核跳到标号start:处开始的汇编代码。它通常关闭中断,禁用cache,设置MMU表,允许中断,并跳到main()这个负责初始化机器不相关代码的C例程。

大多数架构可以调用C例程来启动MMU例程,而不是使用汇编。在某些架构上,由于内存布局的问题,这些代码必须使用汇编。例如,在HP 300机器上,RAM映射在物理地址空间的末尾。也就是说,最后可寻址的字节在地址(2^32)-1处。这意味着当在物理存储的底部加载内核时,最低地址(因此所有变量和例程的地址都在内核里。)依赖于机器上的内存大小。由于这在连接时是不知道的,内核必须使用MMU来映射自己到虚地址0。在允许使用 MUU前设置MMU表项,所以所涉及变量和例程必须清楚的把内核加载的物理地址考虑到。这用C是很难做到的,因此是用汇编写成。

任务切换代码部分的汇编代码保存和恢复机器状态(包括MMU和浮点单元)。其余的由机器不相关的C代码处理。

3.2pmap.c

pmap.c文件处理机器相关的到MMU的接口。机器不相关的虚存(VM)代码,位于/usr/src/vm,为每个进程当前映射保存了一份记录。一旦映射改变了,VM代码调用pmap里的例程来更新MMU状态来反映内核数据结构的改变。pmap里最常见的操作是添加一个页到现存的映射,但是有时必须为 fork()复制一份映射或擦除并为exec()重新产生。Pmap的大部分可以直接基于现存的有类似CPU和MMU的移植。

3.3machdep.c

machdep.c文件包含所有各种于机器相关的例程。大多涉及初始化系统控制台,为内核结构分配内存,处理机器相关部分的进程信号,转储核心映象(core),并处理内核painc,陷入,中断,定时器,奇偶校验,不同的CPU(例如,摩托罗拉68020和68030之间的微小差异),不常见的内存映射,和调试输出。

3.4中断结构

中断结构是指中断优先级。导致中断的硬件事件指定了CPU中断级。CPU可以禁止某个级别和之下的中断,这样可允许重要的中断低优先级的中断,但反之则不同。大多数机器架构不允许软件来重新配置中断结构。如果可重新配置中断优先级,要确保用于任务切换的时钟维持为高优先级的中断,以使低优先级事件(例如访问磁盘)不能禁止提升调度。串口应当在高优先级来确保使用较高的波特率。

中断优先级很重要,因为禁止中断是在内核里提供互斥的常用方法。例如,一个例程修改tty结构(用于处理到终端的输入和输出)会在临界区前调用 spltty()(代表Set Processor Level TTY)并在随后重设为spltty()调用前的级别。在大多数机器上,这个调用会禁止任何可能调用处理tty结构函数的中断,此外,还会禁止低于“tty”优先级的所有中断。对UNIX不合适的中断结构可能导致相当长的用于阻塞更多中断请求(例如定时器,键盘或串口)的中断代码(例如磁盘访问和声音驱动处理)。在Macintosh移植里,频繁使用磁盘会导致系统时间在一天内差了几个小时,和显示波纹,在tty设备里,会取代键盘例程并导致按键失灵。在用于Macintosh的苹果系统V UNIX上,蜂鸣导致串口数据丢失。

3.5非邻接系统内存

内核默认假设内存是按邻接块物理映射的。然而一些机器架构有非邻接物理内存映射,在BSD内核里有处理这个的代码。例如,IBM Pc有从物理内存0开始的RAM,但是ROM和I/O空间映射在640K。因此,别的存储空间要在ROM后开始,在物理地址1024K。

如果要支持非邻接内存,需要定义预处理器常量MACHINE_NONCONTING,并要添加3给函数到pmap.c模块。pmap_next_page ()应当返回“下”页在内存的物理起始地址。第一次调用这个函数时,应当返回最低的物理内存位置。下次调用时,应当返回下一页的起始地址(通常在4096字节以上),如此这般,确保跳过物理存储的空洞。pmap_page_index()应当返回给出物理地址的页数,而pmap_free_pages() 应当返回剩下多少空页。参见i386和Macintosh移植里这三个函数实现。

4设备驱动

为机器写设备驱动即可是移植里最简单的部分也可是最困难的部分,依赖于有多少可用的机器一硬件文档。

在BSD里,对于设备驱动的角色没有严格定义,但是总得来说,一个驱动至少需要作为和硬件的接口。设备驱动(实际对于任何内核模块)的设计者应当自问一下:哪些特征是属于内核的;哪些是属于用户程序。虽然对于一些程序(例如,X Window或串口驱动)很容易做决定,一些内核模块在这两个位置都有参数。例如,SL/IP(串行互联网协议)是在BSD内核实现的,但是有人要问为何所有的用户都要承受只有少数用户才用的模块并且可作为守护程序高效的实现。对于文件系统,特别是很少使用的那种,也可类似实现为由内核调用的用户级守护程序。

在macintosh上,视频显示是以位图实现的并且对于字体也没硬件支持。我们的显示驱动(ITE)支持快速字体绘图,不同尺寸的字体,不同的显卡,不同的显示尺寸,VT220模拟,鼠标指针,剪切和粘贴,虚拟终端,底部滚动等。在团队成员长时间的争论后,最终下的定论是:这个驱动实际是个窗口程序,而不属于内核。移除了所有的代码(除了用于支持小字体和VT220)并放到一个称为dt(desktop的缩写)的程序里,用户登录后就可运行。当把它放到内核里时,就把所有的特征都给用户了,如果需要也允许代码交换出来,可在运行时配置,也易于开发和调试。添加东西到内核之前要仔细审查并要有根据以避免内核膨胀,因为通过把(“驱动”)连接进内核所获得的速度提升并不必要。

4.1串口

串口驱动是有用处的,因为在初始化调试内核时有帮助。串口驱动在大多数机器都易于编写,因为仅涉及到初始化接口,发送字节和接受字节。在引导过程(在 start:标号后,locore起始时)的早期初始化串口是个好想法,以使诊断输出可在引导时打印出来。由于串口驱动是tty驱动,因此需要从头编写,可以简单复制别的移植的串口驱动并根据新硬件修改一些代码。

4.2ITE

大多数计算机挂接了视频监视器来作为系统控制台。监视器或是位图或是字符映射,但是在别的情形下,内核负责显示字符和模拟一个简单的中断,例如 VT220。ite.c文件(internal terminal emulator,内部终端模拟)常用于这个目的。带有位图屏幕的机器可用来于Amiga(如果目标硬件支持图形操作)或Macintosh(如果不支持图形操作)移植的代码。如果目标移植有字符映射屏幕,那么i386移植的代码是作为基础的最好选择。用于VT220模拟的代码可以复制几乎任何一个移植的并很容易实现一个有限状态机。

4.3磁盘(SCSI)

基于SCSI的机器在内核里有两层磁盘代码。scsi.c文件负责处理底层SCSI信息和命令,而sd.c(SCSI disk,SCSI磁盘)文件负责处理分区,块,磁盘访问顺序。NetBSD项目最近移动大多数SCSI磁盘的高层代码到一个机器不相关的目录,因此一个新的移植很可能只要编写适配器想关代码。

大多数SCSI系统可以工作在中断或轮询状态。对于前者,SCSI系统需要请求磁盘,记录所做的请求,接着释放处理器用于别的进程。来自SCSI控制器的中断会导致SCSI系统判断出刚终止的是什么请求,如果需要的话,并传输数据。对于后者,SCSI系统必须处于忙循环直到控制器处理请求;这可能浪费很多 CPU时间。第一个析出(first-cut)的SCSI系统需要使用轮询来最小话可能的bug,但是如果硬件支持的话,最终应当实现一个中断驱动的系统。

4.4键盘

编写键盘驱动并不紧迫,因为串口驱动在移植的早期可以充当控制台。如果到键盘的接口硬件很简单,那么这个驱动可和屏幕驱动一起放到ite.c里。通常从硬件返回的数据是必须转换成ASCII的键控代码。此外支持执行特殊任务的组合键,例如重启机器或显示系统进程表,有时候是有用的。

如果键盘有Alt或命令键,那么可作为元键值处理。例如,如果用户键Alt-E,那么键盘驱动能够模拟<ESC><E>。对于像Emacs这样使用返回键来模拟元键值的程序是有用的。

5制作成产品

Frederick Brooks说过做一个系统程序的难度是做一般程序的三倍,而做系统产品的难度是做系统程序的三倍。由于一个发行的BSD系统是个系统产品,它就要求9倍于普通程序的难度!不仅是开发者必须编写安装工具和文档,他们还要处理有不兼容硬件或没阅读文档而以不正确的方式安装软件的用户。这部分概述了一些在发布一个BSD移植时所需要的工具。

5.1newfs

用户启动一个他之前已经安装了操作系统的计算机。他需要为BSD创建一个新分区(至少40到50M),一个用于swap交换(至少是物理内存的两倍,译者注:这在现在看来就不一定必须了),并格式化这个BSD分区。创建分区最好有本地操作系统附带的工具来做。这里给出一些建议--所遇到的问题依赖于本地操作系统和BSD的相似性。

5.2安装程序

每个移植可以决定如何发行她的二进制程序,但是由NetBSD小组提供的脚本简单易用。这个脚本产生一组可选下载并安装成可工作系统的tar文件。例如,只需要bin.tar,sbin.tar和内核就可引导内核,因为init在/sbin里,shell在/bin里。这对于无法确定这个移植对于他们的配置能否工作

的用乎很有用。

两个可选的通常用于安装tar文件。如果写了软盘驱动并且内核可放到一张软盘上,那么用户可以从软盘引导,挂载内存文件系统并从软盘解压文件。

如果没有可用的软盘驱动,那么运行在本地操作系统山过的程序必须直接写到BSD分区。有需要工作要做,因为基本上整个UFS文件系统都要移植到本地操作系统上。(UFS是伯克利的快速文件系统,现在被FFS取代,伯克利的增强的快速文件系统)。一旦这么做,可以写个特别的允许复制文件到/从BSD文件系统,以及解压,压缩和别的最小化操作的实用程序

第三个选择是,如果本地操作系统允许并且BSD里有个文件系统来读本地操作系统分区,从让安装器从本地分区加载和运行内核。这在我看来是笨拙的,也不可靠,但是可以允许安装工具直接使用UNIX工具,而不用软盘或移植UFS。(这种方法可能会陷入“先有鸡还是先有蛋”的问题,因为内核不知如何挂载本地分区直到它可从中读文件为止。)

5.3FTP站点

发行套件文件和文档必须放到可匿名访问的FTP站点上,并可存放压缩文件(大约需要20M)。确保有个叫做README的文件,它清楚的解释了到那里获得进一步的文档和联系谁来解答问题。

当前,BSD里用于密码加密的代码是不允许输出到美利坚以外的。产生发行套件文件的脚本使所有加密代码放到一个单独的tar文件。其余部分任何人都可下载,并且丢失加密tar文件的用户必须把他们的密码存到简单文本里。确保注意到了FTP站点和README文件里都说明的在美利坚以外下载加密的tar文件是非法的。例如,这些注意事项在sun-lamp.cs.berkeley.edu,NetBSD主站上都说明了:

出口控制注意事项:

非美利坚ftp用户要求遵守美利坚出口控制限制,这意味着如果你在此看到一些DES或别的受限的软件,你不能拷贝它。参见README.export- control(在/和大多数其它目录)获取更多信息。(如果你的国家和美利坚有不受美利坚出口控制限定的协议,那么你不大可能连到这个主机。可到所在国的美国大使馆查证一下。)

5.4邮件列表

用户下载发行套件后,他们也许想要获知所做的修改和更新情况。NetBSD组有一组邮件列表,你可让他们为你的移植创建一个新的列表。任何人都可发邮件到name@NetBSD.ORG(这里的name是你的移植的名字)问问题和帮助他人。

5.5FAQ

大多数新用户都有一些相同的问题,因此在FTP站点做个常见问题(FAQ)是有用的。NetBSD.ORG的邮件列表软件在用户提交后可发送一个短信息;这个信息应当指出FAQ以减少列表里的重复发问。FAQ在最后更新时应当带有日期,目录,到发行套件站点的链接以使用户可从别的站点获取同样的信息并确保获得最新版的。

Linux社区对于他们的文档最近开始使用SGML(Standard Generalized Markup Language)。以SGML写就的文档可自动转换成ASCII,troff,HTML,LaTex和texinfo格式。参见 sunsite.unc.edu下的/pub/Linux/docs目录来获取这个软件。

5.6集成和提高

所移植的代码最终要并入NetBSD官方;联系core@NetBSD.ORG来获取如何做的只是。此外,对于其它移植所做的和机器相关代码的修改保持一致是有用的,你的移植可因此从他们的想法和bug修正中受益。通过发送一个“帮助”信息到maordomo@NetBSD.ORG来加入source-changes列表。

6参考文献

[1]Bach, Maurice J. The Design of the UNIX Operating System, Englewood Cliffs, New Jersey: Prentice Hall, 1986。

[2]Brooks, F. The Mythical Man-Month: Essays on Software Engineering, Reading, Massachusetts: Addison-Wesley Publishing Company, 1975。

[3]Leffler, Samuel J., M. Kirk McKusick, Michael J. Karels, and John S. Quarterman. The Design and Implementation of the 4.3BSD UNIX Operating System, Reading, Massachusetts: Addison-Wesley Publishing Company, 1989。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表