如何在旧台式计算机上构建小型操作系统?

时间:2009-08-03 21:01:43

标签: c operating-system bootstrapping osdev assembly

这可能是徒劳的,因为我知道编写一个操作系统是无法忍受的复杂(尤其是自己)。

  • 我不希望构建下一个linux或windows。

  • 我知道它会很糟糕,而且很麻烦,也行不通,但那没关系。

我想在汇编 C 和(某些) C ++ 中自己编写所有内容。

这是一个未来的项目,因为我现在忙于其他一些事情,没有时间立刻,但我想我现在会问,所以也许我可以得到很多答案,它可以构建并成为这种方法的有用资源(我所看到的其他一切都涉及构建minix,使用现有的引导程序,在虚拟引导程序中构建它等)。

我想用显示器,键盘和鼠标设置一个旧桌面,然后开始处理空白硬盘。

我想学习如何编写我自己的bootloader(我已经找到了很多关于此的资源,但为了完整性,请仍然添加一些好的),我自己的USB驱动程序(如果有必要),CD驱动程序(如果那是必要的)等等,从头开始。

  • 如何将代码放入计算机?用软盘做它最好吗?大多数计算机可以通过USB记忆棒进行操作吗?

  • 我需要哪些司机,你能建议任何建议吗?

  • 启动序列之后 - 那又怎样?我如何进入保护模式等。

  • 如何在没有操作系统帮助的情况下管理内存?我只是使用我想要的任何地址吗?无需初始化?

  • 我无疑会遇到什么会让我感到困惑?

  • 如何将命令行O / S和图形命令行化?

  • 什么是图形操作系统?比如,我会怎样做一些命令行,一个字体和一个顶部的图片?

  • 在哪里可以阅读有关设置多任务处理环境的信息? (即,有两个并排运行的图形命令行)。

  • 我如何设置一种窗口系统?设置简单的多任务处理后,如何在屏幕上显示图形?

相信我,我知道这是一个非常复杂的项目,我可能永远无法完成它或在任何用途上写任何东西。

我还没有提到很多其他的部分,如果你想到的话,也可以自由添加。

请为每个答案添加一个“主题” - 例如,USB驱动程序,然后可能是资源列表,需要注意的事项等。

此外,请不要建议建立另一个操作系统或预先存在的代码。我知道我将读取许多预先存在的代码(例如Linux内核,或示例资源,现有驱动程序等),但最终我想自己完成所有的写作。我知道我应该建立其他东西,而且如果我改变主意并走那条路,那么关于我可以读的很多其他问题。但这一切都是关于从零开始做整件事。

有关如何获取图形的任何建议?不同的视频模式以及如何使用它们等?

20 个答案:

答案 0 :(得分:49)

首先要做的事情。读,读,读,读,读。在希望实现自己的操作系统之前,您需要牢固了解操作系统的工作原理。

抓住Andrew Tanenbaum的一本关于操作系统的书籍。这是我在大学的OS课程中使用的那个:

Modern Operating Systems PDF

Modern Operating Systems on Amazon

尽管有荒谬的封面,但这是一本非常棒的读物,特别是对于教科书而言。 Tanenbaum真的是这方面的专家,他对操作系统如何工作的解释清晰易懂。这本书主要是理论,但我相信他还有一本书,讨论了更多的实现。我从来没有看过它,所以我不能评论它。

这应该可以帮助您了解进程管理,内存管理,文件系统以及操作系统内核需要执行的所有其他操作,以使其达到可引导状态。从那时起,它基本上是为您需要支持的硬件编写设备驱动程序,并提供C库函数的实现,以便为打开文件和设备,读取和写入,在进程之间传递消息等内容进行内核调用。

阅读x86程序集(假设您正在为x86计算机设计此程序)。对于在处理器操作模式之间移动,这应该回答了很多问题。

如果你有任何电子知识,那么从为具有充足文档的嵌入式设备编写操作系统开始可能会更容易,因为它通常比x86 PC更简单。我一直想编写自己的操作系统,我开始从Digilent为This Development Board编写微内核嵌入式操作系统。它可以运行Xilinx的软核MicroBlaze处理器,该处理器具有非常全面的文档。它还有一些RAM,闪存数据存储,LED,开关,按钮,VGA输出等。为编写简单的驱动程序,可以玩很多东西。

嵌入式设备的一个好处是,您可以避免长时间写入VGA驱动程序。在我的例子中,Digilent开发板有一个板载UART,因此我可以有效地使用串行输出作为我的控制台来完成整个操作并以最小的麻烦启动到命令行。

只要确保您选择的任何目标都有一个现成的,经过良好测试的编译器。你想要同时编写操作系统和编译器。

答案 1 :(得分:28)

http://www.osdev.org/http://www.osdever.net/

欢迎来到OS开发世界。

另请参阅SO的 tag wiki中的其他x86文档链接:Intel和AMD手册,编译器/汇编程序文档以及各种指南。

它还建议使用BOCHS或其他虚拟环境进行调试,因为您可以单步执行引导加载程序并检查寄存器。

答案 2 :(得分:15)

我建议至少在一开始就在Bochs或其他虚拟机上工作,原因是你可以随身携带它,它更容易调试(你可以看到的确切状态)硬件),如果您需要外部帮助调试,他们可以使用与您完全相同的“硬件”。

我最有用的建议是让自己进入一个可以尽快运行C代码的状态 - 即启动,设置描述符表,并让自己达到可以安全运行编译的程度C.如果你想要保持理智并继续努力,大多数内核都应该在C中。装配虽然在某些地方是必需的,但是很乏味且难以调试。

答案 3 :(得分:14)

在最低级别,操作系统需要做的最低限度是以某种方式驱动系统的硬件,并以某种方式加载执行某种“用户代码”。如果您要从PC开始,那么您需要编写可以从某个设备或其他设备加载的代码。较旧的PC在固件中具有BIOS,其确定硬件如何执行一些初始化(至少视频,键盘以及某种形式的存储或引导加载程序)。 (2017年10月更新:较新的PC具有EFI或UEFI固件......这在很大程度上是一种迂腐的差异;本讨论的目的与此相同。)

首先,在目标系统上学习如何使用BIOS或其他固件的低级细节。也就是说,学习如何编写BIOS可以加载和执行的程序。这最终会变成你的引导装载程序。从小处开始。只需一个程序打印:“Hello,Linus”直接来自固件启动过程(在软盘或USB拇指驱动器上,这将是一个良好的开端......或者如果您愿意,可以在硬盘驱动器上)。

从那里我建议编写一个非常简单的串行驱动程序...更新你的启动加载程序以初始化一些串口,并从那里开始下载。然后它可以执行它拉过的代码。从那里写一些可以写入另一组块的引导程序(我们还没有实现文件系统......甚至没有分区表解析;所以我们首先处理磁盘上原始的块范围)。

此时,您的引导加载程序应该能够在串行线上提取新代码,将其转储到分区中(是的,实现某种分区表处理......是否符合标准PC约定由您自己决定)此时),并执行它。

从那里你应该能够处理更复杂的功能。从这个基础你可以编写和编译一个新的“内核”...重新启动你的测试平台,并将新的内核部署到它。

(你的引导加载程序应该接收一些信号,比如BREAK通过串行握手线作为跳过下载的命令,只是启动现有的图像;它也应该以这种方式处理一些超时。)

从那里写一个非常简单的终端层和命令shell?一个文件系统?实现命令以下载除内核之外的新可执行内容(某种文件或对象)。等等。

当然,您可以使用PC键盘和视频启动控制台驱动程序(如果我没记错的话,分别是BIOS INT 0x16h和INT 0x10H的东西)。但是,我建议从串行驱动程序开始,因为您可以从任何其他现有(功能)系统自动化构建/部署/测试周期。由于您的新操作系统将作为交叉编译项目启动,因此您必须采用简化的方式来处理该操作系统。

我不知道你想把你的项目带到多远。一个相当令人印象深刻的目标是实现“自我托管”。如果你可以创建一个简单的汇编程序/编译器,它可以让你使用你的新操作系统来(重新)构建,链接和启动到新操作系统的工作版本......那么你已经实现了这个目标。 (请注意,这不是必需的。许多嵌入式系统永远不会自我托管,并且没有任何问题。)

答案 4 :(得分:12)

如果您不介意使用硬件虚拟化,那么有一门课程(书籍+讲座+软件)将带您“从Nand到俄罗斯方块”。您可以完全自己创建一个完整的计算机系统(用于原子和给定的电子与非门),直到构建操作系统,一种语言,最后在您的个人计算机上编写一个简单的游戏。

我认为这是一个好主意,我完全打算很快陷入困境。这本书出奇的便宜,我相信这门课程是在麻省理工学院教授的。我可以想象没有比从头开始构建自己构建的整个系统的全面,完整知识更好的感觉。

链接:http://www1.idc.ac.il/tecs/

答案 5 :(得分:10)

我会从小规模开始购买8086嵌入式开发套件,并开发一个多任务操作系统。有了内核并熟悉硬件级别的工作后,您就可以做更具挑战性的事情了。

建立一个VGA显示器DOS克隆是一个相当具有挑战性的事情。细节是巨大的。 : - )

具体主题。

如何将代码放入计算机?用软盘做它最好吗?大多数计算机可以通过USB记忆棒完成吗?

BIOS将进行基本自举。


我需要哪些司机,你能建议任何建议吗?

任何不是直接cpu /内存操作的东西。任何不直接在CPU参考手册中的内容。


启动序列之后 - 然后是什么?我如何进入保护模式等。

保护模式将成为启动序列的一部分。

然后你开始多任务并找出如何启动流程。


如何在没有操作系统帮助的情况下管理内存?我只是使用我想要的任何地址吗?没有必要初始化?

正确。您可能最终想要整理虚拟内存系统。


毫无疑问,我会遇到什么会让我感到困惑?

没有调试工具,没有IO


如何将命令行O / S和图形命令生成?

悲伤。查找Windows 3.1和Linux,特别是X windows。


什么是图形操作系统?比如,我该怎样做一些命令行,一个字体,一个顶部的图片?

查看X窗口。


最后的建议:研究linux / x windows。它并不完美,但它提供了对一个方法的理解。还研究嵌入式系统。

答案 6 :(得分:8)

尝试阅读一个小型的基本开源操作系统的代码,例如MikeOS。

或者,我建议采取以下步骤(应该很有趣!):

  1. 编写虚拟机。定义所有处理器指令,以便您了解内部和外部的系统。与SDL接口,用于键盘,鼠标,屏幕,音频访问。保持简单,以便您可以立即适应您的头脑。它不需要是最先进的虚拟机,只需一个可以模拟“真实”计算机功能的虚拟机。
  2. 为虚拟机的处理器编写汇编程序。请记住,这个汇编程序不一定是用虚拟机语言编写的程序,而是任何可以将汇编语言转换为机器代码的程序。
  3. 定义可执行格式,并编写一个简单的链接器。
  4. 您已经拥有了编写操作系统的所有部件!用汇编语言编写它,组装它......等等。你不需要这么复杂的引导加载过程,只需先让你的机器运行你的操作系统。
  5. 上面的步骤对于编写一个简单的操作系统来说似乎有些愚蠢,但是嘿,这很有趣。

答案 7 :(得分:8)

我看到很多关于操作系统开发网站的很好的参考,所以我将描述一种不同的方法:

如果您想要从裸机实施操作系统的经验,那么硬件选择的方式比旧PC要好。使用PC架构,您将花费大量时间编写其30年设计历史中不感兴趣的工件。例如,只是项目的引导加载程序部分可能已经烧毁了许多勇敢的程序员。

例如,您需要一组驱动程序才能从磁盘和/或网络中读取内核。然后你需要代码才能进入保护模式。那时,你需要另一组驱动程序!在这一点之后,你可以做很少的工作来让芯片进入保护模式。你想在不同的PC上运行它4 - 4年,你还需要另一组驱动程序。

研究自举ARM或其他32位“嵌入式”芯片。可以使用廉价的开发板,也可以自己焊接!有些内置以太网和USB。我认为你会在一个理智的,非硬度的架构上工作更有乐趣,也许最终会有一些可重复使用的技能。

答案 8 :(得分:8)

最重要的是,如果您希望在真实硬件上运行,您绝对需要处理器手册的副本。英特尔手册(http://www.intel.com/products/processor/manuals/)非常宝贵。他们讨论从切换模式(真实/受保护)到虚拟内存管理(如果你选择那么远)到制作系统调用(如果你曾经做过用户模式)的所有事情。 最重要的是他们非常详细地解释了许多必须设置的东西,比如TSS和段寄存器,大多数操作系统文本都没有讨论,因为他们更关心比处理器特定的细节更高级的概念。

答案 9 :(得分:8)

OS Development Series @ BrokenThorn可能会让您感兴趣。

答案 10 :(得分:6)

结帐MikeOS。它编写的一个相当简单的操作系统是可读的(如在注释中)汇编。尽管它非常简单,但它确实有一个GUI并支持一些网络和多媒体。

修改MenuetOS是图形化的。它也写得很直接,但它比MikeOS更复杂。

答案 11 :(得分:6)

你有一个雄心勃勃的目标。但执行是关键。

大多数结构化方法(教科书或大学课程)将引导您完成整个过程,但它们提供了许多细节代码,这些代码掩盖了您所选平台的神秘细节,让您专注于大 - 图片创意:流程调度,内存管理,死锁预防,I / O等。

我的建议是这样:缩短你的期望并从一个基本问题开始。

什么是操作系统?

计算机科学家(希望)永远不会说操作系统是图形用户界面,网络浏览器,连接USB设备的方式,或用户实际可以看到或触摸的任何东西。相反,最基本的操作系统是我上面提到的那些。他们都属于一个大伞:资源管理。

操作系统只不过是一个管理计算机硬件资源的程序:内存,CPU和外围设备。

这是一个简单的操作系统:程序允许用户使用串行连接键入程序(十六进制或二进制)。输入程序后,它将运行该程序。程序完成后,控制权将返回给用户,他们可以再次运行程序或输入新程序。

在“干净”架构上执行此操作,例如具有64K内存的嵌入式ARM处理器。在了解ARM的详细信息几天后,您可以在汇编中对其进行编码。 瞧!,你已经拥有了一个操作系统。

它可以完成操作系统应该做的所有事情:

  • 它通过不让用户覆盖操作系统本身来管理内存。
  • 它计划运行一个进程。
  • 它处理单个串行外设的I / O.

这为您提供了一个构建块。你现在有很多选择。也许其中一个是允许将两个程序加载到内存中,让用户决定下一个程序运行。

或者您可以让用户暂停执行一个程序,切换到另一个程序,暂停和切换回来。这是基本的多任务处理,即使它完全是手动的。

你的选择是无限的,但每一个都是你以前的一步。

如果你没有把目光放得太高,这很有趣!

答案 12 :(得分:5)

我在StackOverflow上维护一个资源列表:How to get started in operating system development。当你开始冒险时,请为它添加新的资源(我即将开始:))

答案 13 :(得分:4)

许多学校都有OS课程,可以完成您所描述的大部分内容。我的学校(CMU)用C语言教授操作系统,我们编写了一个内核,文件系统和shell,并提供了启动加载程序的代码。

不幸的是,我无法在网上找到这门课程(15-412)的任何权威资源,而且它随着时间的推移而发展。但是,也许人们可以在网络上发布具有良好资源的学校发布信息来源和作业的链接。

答案 14 :(得分:3)

研究A2 System(以前称为 Oberon系统),了解您可以窃取的想法。这是一个由两个人建造的图形操作系统,尽管其中一个是Niklaus Wirth。 1990年左右首次发布,速度惊人的好。 Gutknecht有一本书。

答案 15 :(得分:3)

关于低级图形编程,这将为您提供大量信息:http://www.osdever.net/FreeVGA/home.htm。 (对于文本模式也很有趣。)

  

我无疑会遇到什么会让我感到困惑?

你会发现在PC上有很多东西都不清楚:x86指令集本身很复杂,当你直接访问硬件时,你需要花一点时间才能理解如何编写单个屏幕上的角色。

不要担心软盘等,大多数情况下你会使用Bochs或QEmu等仿真器。

答案 16 :(得分:3)

您可能需要考虑查看Operating Systems Concepts, by Abraham Silberschatz - 了解系统编程概念是一项基本要求,请查看操作系统linux * BSD和GNU/Linux的F / OSS内核内部,尤其是更早版本,可能更多文档。alt text alt text

答案 17 :(得分:3)

您可能会喜欢名为“滚动自己的玩具UNIX-clone操作系统”的this教程,它非常有见地,应该会帮助您。

祝你好运。

答案 18 :(得分:2)

看看Minix。研究源代码以及“Operating Systems Design and Implementation”。考虑为项目做出贡献。我认为Minix是一个非常好的和有前途的操作系统。它也是资金充足的项目。这意味着,您甚至可以通过捐款获得报酬!

答案 19 :(得分:1)

由于BIOS已经内置了许多输入/输出功能,用于更改屏幕模式,更改像素颜色,将文本写入屏幕以及许多其他内容,因此非常容易实现。但是,它不包括对文件系统的支持,这是您必须在操作系统中包含的极少数事项之一。

BIOS加载硬盘驱动器上的第一个扇区并从那里开始执行代码,因此必须将操作系统放在硬盘驱动器上第一个扇区的第一个指令处。

这篇维基百科文章应该让您开始使用BIOS中断,将文本写入屏幕,从键盘接收键和其他内容。 https://en.wikipedia.org/wiki/BIOS_interrupt_call

即使您打算使用c ++,我也强烈建议您阅读汇编编程,因为这对理解硬件的工作原理至关重要。