如何在旧台式电脑上构建一个小型操作系统?涉及IT技术。

116

我知道写一个操作系统非常复杂,尤其是一个人。

  • 我不指望能建立下一个Linux或Windows。

  • 我知道它会很糟糕、很多错误,并且无法正常工作,但这没关系。

我想用AssemblyC和(一些)C++自己编写所有东西。

这是一个未来的项目,因为我现在忙于其他事情,没有立即的时间,但我想我现在就问一下,这样也许我可以得到很多答案,它可以积累起来成为这种方法的一个有用的资源(我所看到的其他所有内容都涉及构建minix,使用现有的引导程序,或在虚拟启动程序中构建,等等)。

我想用一个旧的桌面计算机配上显示器、键盘和鼠标开始工作,在一个空白的硬盘上。

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

  • 我如何将代码放入计算机?最好用软盘吗?大多数计算机可以使用USB驱动器吗?

  • 我需要哪些驱动程序,并且您能推荐建立这些驱动程序的参考资料吗?

  • 引导程序之后-然后呢?我如何进入保护模式等等。

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

  • 我肯定会遇到什么困扰我迷惑的问题?

  • 如何使它成为命令行操作系统和图形化操作系统?

  • 一个图形化操作系统是建立在什么基础上的?比如,我该怎样做出一个带有字体和顶部图片的命令行界面?

  • 在哪里可以阅读有关设置多任务环境的资料?(例如,同时运行两个类似图形化的命令行)

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

  • 相信我,我知道这是个非常复杂的项目,而且我可能永远都不会完成它或写出任何有用的东西。

    还有许多其他方面我没有提到,如果你想到了什么,请随意添加。

    请每个答案只回答一个主题,例如USB驱动程序,然后列出资源、注意事项等。

    另外,请不要建议建立在其他操作系统或现有代码的基础上。我知道我会阅读很多现有的代码(例如Linux内核、示例资源、现有的驱动程序等),但最终我想自己编写所有内容。我知道我应该建立在别的东西的基础上,而且也有许多其他关于这方面的问题,如果我改变主意并采用那种方法,我可以阅读这些问题。但是这个问题是关于从零开始完成整个项目的。

    有没有关于如何获得图形化界面的建议?不同的视频模式以及如何使用它们等等?


    14
    这是我最大的目标。我非常想编写一个操作系统,只是为了好玩和学习……但过去几年里我一直没有时间。如果你需要帮忙或者只是想与我讨论一些问题,你可以通过 schmeling88@gmail.com 给我发邮件。 - Max Schmeling
    2
    @Max和@Tom,我也遇到了这个bug。我现在正准备开始这个项目 :) - Giovanni Galbo
    2
    现在先不要考虑图形。Unix从未直接支持图形,这并不是什么坏事。:-)但基本上没有简单且可移植的方法来超越800x600,如果我没记错的话。 - Bastien Léonard
    2
    投票关闭,原因是问题过于宽泛。类似于:https://dev59.com/6HVC5IYBdhLWcg3wjx5d || http://stackoverflow.com/questions/2800741/how-to-create-your-own-x86-operating-system-for-modern-pc-computers?rq=1 - Ciro Santilli OurBigBook.com
    1
    为什么?这个问题已经古老了,不再产生任何活动。谁在乎呢? - Carson Myers
    相关问答:通用引导程序开发技巧 / 如何为我的引导程序制作内核? 具有在传统BIOS模式下启动的x86 PC的工作Hello World内核(不是UEFI),具有切换到32位保护模式并运行C内核的引导程序。 - Peter Cordes
    20个回答

    52

    首先,阅读、阅读、再阅读。在实现自己的操作系统之前,您需要充分理解操作系统的工作原理。

    获取Andrew Tanenbaum关于操作系统的书籍之一。这是我在大学操作系统课程中使用的版本:

    《现代操作系统》PDF

    《现代操作系统》在亚马逊上的链接

    虽然封面有点荒谬,但是这是一本非常棒的读物,特别是对于一本教科书而言。Tanenbaum确实是这个领域的专家,他对操作系统底层工作原理的解释清晰易懂。这本书主要讲解理论,但是我相信他还有一本书涉及更多的实现内容。不过,我从未阅读过它,因此无法评论它。

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

    阅读x86汇编语言(假设您正在为x86机器设计此操作系统)。这应该可以回答许多关于在处理器操作模式之间移动的问题。

    如果您具备电子知识,那么从编写嵌入式设备的操作系统开始可能会更容易,因为相比x86 PC而言,它通常会更简单,并拥有丰富的文档。我一直想编写自己的操作系统,并开始编写Digilent公司的这个开发板上的微内核嵌入式操作系统,该开发板可以运行Xilinx的软核MicroBlaze处理器,该处理器有非常详细的文档。此外,它还配备了一些RAM、闪存数据存储、LED、开关、按钮、VGA输出等组件,足够我们尝试编写简单驱动程序。
    另一个嵌入式设备的好处是,您可能很长时间都不需要编写VGA驱动程序。在我的情况下,Digilent开发板上有一个UART接口,因此我可以有效地使用串行输出作为我的控制台,以最小的麻烦将整个操作系统启动并引导到命令行控制台。
    只需确保您选择的目标平台具有易于获取和经过充分测试的编译器。您不希望同时编写操作系统和编译器。

    2
    +1,但我更喜欢Tanenbaum的Minix书(更注重实现),而且没有必要只专注于理论。无论如何,他不会在第一次尝试时就编写操作系统。他将首先编写引导加载程序,然后切换到保护模式,然后处理I/O等等。 - Bastien Léonard
    2
    为嵌入式芯片编写操作系统是一项非常有价值的工作。在完成后,你会感到自己创造了独特的东西,而且相比于为x86编写操作系统,这要简单得多,但核心概念仍然保持不变。例如,可以看看TinyOS(虽然它在技术上不是一个操作系统,但其中包含调度程序和任务模块等内容)。 - Kristopher Micinski

    29

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

    欢迎来到操作系统开发的世界。

    此外,还可以在SO的 标签wiki中查看其他x86文档链接:Intel和AMD手册、编译器/汇编器文档以及各种指南。

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


    1
    特别是http://wiki.osdev.org! - Matthew Iselin
    不要忘记 http://forums.osdever.net :) - Brenden
    6
    我知道这些资源很有用,但我认为如果你提供一些背景信息而不仅仅是一组没有说明的链接,对于未来的读者可能会更有帮助。 - icktoofay
    @icktoofay 这个问题太宽泛了,我认为无法得出恰当的答案。 - user253751

    15

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

    我最有用的建议是尽快使自己能够运行C代码--即启动、设置您的描述符表,并将自己带到一个安全运行编译的C代码的状态。如果您想保持理智并继续开发它,大多数(如果不是全部)内核应该采用C代码编写。汇编语言虽然在某些地方是必需的,但往往很繁琐且难以调试。


    我现在会研究一下Bochs,但最终我想在某台PC上构建它。 - Carson Myers
    如果在BOCHS中运行正常,通常情况下,在真实的PC上也会正常工作,除了它们的BIOS存在差异。大多数错误可能会影响BOCHS和真实硬件,但不同之处在于,当您的代码在BOCHS中陷入无限循环时,您可以使用BOCHS内置的调试器找出位置,并单步查找如何/为什么。在真实的硬件上,您只能添加调试打印。使用调试器将节省数小时和数天的头痛。 - Peter Cordes

    14
    在最基本的层面上,操作系统需要能够以某种方式驱动系统的硬件,并加载执行某种形式的“用户代码”。如果你要从 PC 开始,那么你需要编写可由其从某个设备加载的代码。旧款 PC 上有一个固件 BIOS,它确定硬件如何进行一些初始化(至少是视频、键盘和某种形式的存储或引导加载程序)。(更新于 2017 年 10 月:新款 PC 有 EFI 或 UEFI 固件……这在很大程度上是一种追求严谨的区别;对于本讨论来说,它们具有相同的目的)。
    因此,首先要学习如何在目标系统上使用 BIOS 或其他固件的低级细节。也就是说,学习如何编写 BIOS 可以加载和执行的程序。这将最终演变成您的引导加载程序。从小处开始。只需获得一个可以直接从固件引导过程中打印“Hello,Linus”的程序(从软盘、USB 拇指驱动器开始可能是一个不错的选择……或者从硬盘开始,如果你愿意的话)。
    从那里,我建议写一个非常简单的串行驱动程序……更新你的引导加载程序以初始化某个串口,并从那里开始下载。然后它可以执行它拉过来的代码。从那里编写一些引导程序,可以写入另一组块(我们还没有实现文件系统……甚至没有分区表解析;因此,我们将首先处理原始块范围)。
    在这一点上,你的引导加载程序应该能够通过串行线拉取新的代码,将其转储到分区中(是的,实现某种分区表处理方式……是否符合标准 PC 约定取决于你此时的选择),并执行它。
    从那里开始,你应该能够处理更加复杂的功能。基于这个基础,你可以编写和编译一个新的“内核”……重新启动你的测试平台,并将新内核部署到其中。
    (你的引导加载程序应该采取一些信号,比如在串行握手线上的 BREAK 作为跳过下载并仅引导现有映像的命令,并处理一些超时方式。)

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

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

    我不知道您希望将项目推到哪个阶段。一个相当令人印象深刻的目标是实现“自主托管”。如果您可以创建一个简单的汇编程序/编译器,使您能够使用您的新操作系统重新构建、链接和引导进入工作版本的新操作系统...那么您已经实现了该目标。(请注意,这不是必需的。许多嵌入式系统永远无法自我托管,这没有问题)。


    在现代硬件上,让串行驱动程序正常工作可能比编写控制台(视频/键盘)驱动程序更加困难。自从我写这篇文章以来,传统的串行连接器在现代台式机和笔记本电脑上已经几乎不存在了。一些嵌入式和“业余爱好者”硬件仍然具有老式的RS-232C接口,无需通过USB仿真即可使用。例如:http://www.mpl.ch/t2600.html 似乎具备此功能。 - Jim Dennis

    12
    如果您不介意使用硬件虚拟化技术,那么有一个课程(书籍+讲座+软件)可以帮助您从“门电路”到“计算机”。您将完全自己创建一个计算机系统,从最基本的电子元器件NAND门开始,一直构建整个操作系统、语言,最终在您自己的计算机上编写简单的游戏。
    我认为这是一个很好的主意,我完全打算尽早开始。这本书价格惊人便宜,我相信这门课程是在MIT教授的。我无法想象比拥有自己从头到尾构建的完整系统更令人兴奋的事情了。
    链接:http://www1.idc.ac.il/tecs/

    我认为这个链接已经失效了。有人知道其他访问方式吗? - Koray Tugay
    1
    @KorayTugay http://nand2tetris.org/ - user253751

    10

    我建议从购买一个8086嵌入式开发套件开始,开发一个多任务操作系统。当你拥有内核并熟悉在硬件层面上工作时,你就可以准备做一些更具挑战性的事情。

    即使是构建一个VGA显示的DOS克隆也是一项相当具有挑战性的工作,细节非常繁琐。 :-)

    具体主题。

    如何将代码放到计算机上?最好使用软盘吗?大多数计算机能否使用USB存储器?

    BIOS会进行基本的引导。


    我需要哪些驱动程序,您能推荐任何相关的构建参考资料吗?

    除了直接的cpu/内存操作之外,其他都需要。 除了CPU参考手册中直接描述的内容之外。


    引导序列之后——然后呢?我怎样进入保护模式等等?

    保护模式将成为引导序列的一部分。

    然后,您可以开始多任务处理并找出如何启动进程。


    如果没有操作系统的帮助,我该如何管理内存?我只需要使用任意地址吗?不需要初始化吗?

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


    我肯定会遇到什么困扰?

    没有调试工具,没有IO。


    如何将其变成命令行操作系统或图形化操作系统?

    需要付出努力。查阅Windows 3.1和Linux,特别是X Windows。


    图形化操作系统建立在什么基础之上?比如,我该如何做一个有字体和图片的命令行界面?

    查阅X Windows。


    最后的建议:学习Linux/X Windows。它并不完美,但提供了一种方法的理解。同时也要学习嵌入式系统。


    非常好的答案,我已经准备好了Linux内核,我一定会研究Windows 3.1。 - Carson Myers

    8

    如果你想在真实的硬件上运行这个程序,最重要的是你需要一份处理器手册。英特尔手册(http://www.intel.com/products/processor/manuals/)是非常有价值的。它们详细介绍了从切换模式(实模式/保护模式)到虚拟内存管理(如果你选择深入了解)再到系统调用(如果你进入用户模式)等所有内容。最重要的是,它们详细解释了许多必须设置的东西才能使程序正常工作,例如TSS和段寄存器,而大多数操作系统文本不会涉及这些内容,因为它们更关注于高级概念而不是处理器特定的细节。


    你可以通过Intel免费获取纸质副本。 - Matthew Iselin

    8

    他们的代码有问题。但教程本身很棒。 - Kamila Szewczyk

    8

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

    如果你想从零开始实现一个操作系统,那么有比旧PC更好的硬件选择。使用PC架构,你将花费大量时间编写无趣的代码,以解决其30年设计历史中的问题。例如,项目的引导程序部分可能已经让许多勇敢的程序员筋疲力尽。

    例如,您需要一组驱动程序来从磁盘和/或网络上读取内核。然后,您需要编写代码进入保护模式。此时,您需要另一组驱动程序!在将芯片置于保护模式之前,您所做的工作很少能够转移。如果您想在不同的PC上运行它,跨度约为4年,您将需要另一组驱动程序。

    考虑引导ARM或其他32位“嵌入式”芯片。可以购买廉价的开发板,也可以自己焊接!一些开发板具有内置以太网和USB。我认为,您将会在一个明智、非陈旧的架构上工作,并最终获得一些可重用的技能,这样您会更有乐趣。


    不完全是我要求的,但+1让我陷入了阅读的漩涡。 - Carson Myers
    Marsh给了你很好的建议。x86/BIOS架构的低级细节非常复杂。你可能会陷入这些细节中,无法专注于像内存管理和进程调度这样更大的问题。选择一个“更干净”的串口架构。从长远来看,你会更加快乐。 - Barry Brown

    8
    尝试阅读一些小型基础开源操作系统的代码,例如MikeOS。
    或者,我建议执行以下步骤(应该很有趣!):
    1.编写一个虚拟机。定义所有处理器指令,以便您全面了解自己的系统。将其与SDL接口连接,以便访问键盘、鼠标、屏幕和音频。保持简单,以便您可以一次性掌握所有内容。它不需要是最先进的虚拟机,只需要能够模拟“真实”计算机的功能即可。
    2.为虚拟机的处理器编写汇编器。请记住,这个汇编器不必是用虚拟机语言编写的程序,任何可以将汇编语言转换为机器码的东西都可以。
    3.定义一个可执行格式,并编写一个简单的链接器。
    4.现在你已经拥有编写操作系统所需的所有部件了!用汇编语言编写它,汇编它……等等……你不需要如此复杂的引导过程,只需让您的机器首先运行您的操作系统即可。
    以上步骤可能对于编写简单的操作系统来说似乎有点愚蠢,但嘿,这很有趣。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接