Creating an Operating System

来自osdev
Zhang3讨论 | 贡献2022年1月17日 (一) 05:48的版本 (创建页面,内容为“{{Rating|4}} 欢迎来到操作系统开发! 本教程将记录从婴儿步骤到创建自托管操作系统的创建新操作系统的过程。 这条路漫长而艰难,但又有趣又有收获。 随着你逐步完成这些阶段,你将逐渐开始偏离本教程,因为你对操作系统的设计做出自己的决定,并且不再需要本指南。 如果你创建了一个非类Unix的操作系统,那么你将会更早出现分歧,并且必须自…”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索
难度等级
Difficulty 4.png
大师

欢迎来到操作系统开发! 本教程将记录从婴儿步骤到创建自托管操作系统的创建新操作系统的过程。 这条路漫长而艰难,但又有趣又有收获。 随着你逐步完成这些阶段,你将逐渐开始偏离本教程,因为你对操作系统的设计做出自己的决定,并且不再需要本指南。 如果你创建了一个非类Unix的操作系统,那么你将会更早出现分歧,并且必须自己填补缺失的空白。

阶段0: 介绍

欢迎来到操作系统开发

正文: Introduction

在开始编写操作系统之前,你应该查阅所有基本文档。

构建最新的GCC

正文: Building GCC

在开始进行操作系统开发并构建交叉编译器之前,你可能希望将系统编译器升级到最新版本。

第一阶段: 开始

在此阶段,我们将建立一个工具链并创建一个基本内核,该内核将成为新操作系统的核心。

设置跨平台工具链

正文: GCC Cross Compiler

你想做的第一件事是为你的操作系统设置一个交叉编译器。 本地系统上的编译器无法为你的操作系统生成程序,因为它尚未被发明。 首先,你要做的是创建一个编译器,该编译器生成将直接在目标硬件上运行的可执行文件。

创建一个Hello World内核

正文: Bare Bones
另见 Bare Bones for other platforms

你的下一个任务是制作一个简单的hello world内核,该内核能够启动,将消息打印到输出设备,然后无休止地循环。 虽然简单而无用,但它将作为一个真实系统的一个很好的例子和起点,并确认你的测试环境正常工作。

设立一个项目

正文: Meaty Skeleton

通过一个基本的工作示例,你的下一个任务是使用你认为合适的构建系统来设置构建基础架构。 在选择技术时要小心,GNU Make比Python更容易移植。

调用全局构造函数

正文: Calling Global Constructors

编译器希望你执行各种程序初始化任务,例如调用全局C对象上的构造函数。 通常,你将使用 kernel_early_main 函数来设置最小内核功能,然后执行所有这些初始化任务,然后跳转到实际的 kernel_main 函数。

终端支持

正文: Formatted Printing

你将经常需要调试你的操作系统。 你最好的朋友是一个printf函数,它能够将字符串和整数打印到屏幕上的类似终端的缓冲区。 尽早将printf函数添加到内核中至关重要,因为以后肯定需要它进行调试。

Stack Smash Protector 堆栈粉碎保护器

正文: Stack Smashing Protector

考虑安全性和健壮性还为时过早。 你可以利用现代编译器提供的可选堆栈粉碎保护器,这些编译器可以检测堆栈缓冲区溢出,而不是表现出乎意料 (或者什么都没有发生,如果不幸的话)。

多引导

正文: Multiboot

了解引导加载程序为内核提供的功能和信息非常有用,因为这可能有助于你获取内存映射,设置视频模式,甚至内核符号表。

Global Descriptor Table

正文: Global Descriptor Table

全局描述符表是处理器状态的重要组成部分,因此它应该是初始化的第一件事之一。 即使在kernel_early之前进行设置也可能很有意义。

Memory Management

正文: Memory Management

内存分配和管理是操作系统中最基本的功能之一。 你需要跟踪物理页面框架,使用的虚拟内存范围以及在其上实现堆 (malloc,free) 以供内部内核使用。

中断

正文: Interrupts

你的内核需要处理硬件发送的异步事件才能正常运行。

多线程内核

正文: Multithreaded Kernel

最好在内核开发的早期进行多线程处理,否则最终将重写内核的一部分。 当我们稍后添加进程时,我们肯定会需要这个。

Keyboard

正文: Keyboard

你的操作系统肯定需要从计算机操作员读取输入的支持,以便它可以使其行为适应他的意愿。

Internal Kernel Debugger

正文: Internal Kernel Debugger

对于多线程内核来说,早期具有内置的调试功能非常有用。 你可以有一个神奇的键,它可以停止整个内核,并将用户转储到一个带有命令行界面的迷你内核进行调试。 它可以知道调度程序用来列出所有线程并执行调用跟踪的数据结构。

文件系统支持

Main articles: Filesystem, Initialization Ramdisk

尽早支持文件系统并使用初始化ramdisk将文件传输到操作系统上会很有用。

第二阶段: 用户空间

在此阶段,我们将把你的操作系统扩展到用户空间,并增加对程序的支持,这足以使你的项目成为小型操作系统。 在此阶段的早期,你需要处理系统调用,程序加载,内存管理和系统的返工部分。

User-Space

正文: User-Space

到目前为止,你的procesessor已在内核模式下运行,代码可以执行所有操作。 进程通常在完全没有权限的情况下运行,除了能够执行代码并使用其指定的内存。 实现用户空间的第一部分是将处理器切换到用户模式。

程序加载

正文: Dynamic Linker

你需要完成的第一个任务是将程序加载到内存中。 这涉及解析程序标头,在正确的虚拟地址处分配内存以及将段的内容复制到正确的虚拟地址。 你还需要根据重定位表填写GOT中的条目。

System Calls

正文: System Calls

你现在可以将程序加载到内存中并切换到使用模式。 进程使用系统调用与内核通信,这是你要添加的下一个功能。

操作系统特定工具链

正文: OS Specific Toolchain

由于你的操作系统现在正在成为一个真正的操作系统,是时候这样对待它了。 我们想教交叉编译器有关你的操作系统及其约定的信息,因此我们可以轻松地交叉编译程序。

Creating a C Library

正文: Creating a C Library

此时,你可以决定使用现有的C库或编写自己的C库。 如果你采用自定义路由,则需要设置交叉编译器为libgcc所需的一些基本功能。 有了这个,你现在可以很容易地交叉编译程序。

分支并执行

正文: Fork

在基本程序加载到位的情况下,我们几乎可以创建一个多任务操作系统。 缺少的原语允许进程创建新进程。 标准的Unix原语是fork,它允许进程创建自己的完美副本。 然后,该副本能够调用程序加载器,并用另一个程序映像的内存替换其自己的内存。

Shell

正文: Shell

这是你的操作系统中非常令人兴奋的一点。 它能够运行程序和创建新进程。 到目前为止,系统的行为可能已经在编译时确定。 通过编写shell,你可以运行多个程序,并决定在运行时运行哪个程序。 这就是你达到许多新手梦想的水平的地方: 具有正常工作的命令行的基本操作系统。

第三阶段: 扩展你的操作系统

有了这些基本功能,你现在就可以开始编写你的操作系统及其所有精彩功能了。 你将添加游戏,编辑器,测试程序,命令行实用程序,驱动程序以及你可以想象的任何内容。 你的技能和想象力是这里的极限。 你可以将这些功能中的许多功能延迟到以后在你的操作系统中,然后以几乎任何顺序进行。

Time

正文: Time

时间是计算中的一个复杂概念,但是现代操作系统有望具有将时间戳转换为解析时间和返回的功能,以及提供系统时钟 (实时,单调时间,用户CPU时间,..) 和计时器在这些时钟上发生过期事件。

线程

正文: Thread

Operating systems should expose a threading API such as pthreads.

Thread Local Storage

正文: Thread Local Storage

线程局部变量需要运行时支持。

对称多处理

正文: SMP

这是一个非常好的主意,在早期添加对多个cpu的支持到你的内核,或者你可能需要重做很多内核,因为它在很多地方都没有SMP就绪。

辅助存储

正文: Secondary

你可能希望支持常见的块设备,例如硬盘,cdrom,软盘以及操作系统需要支持的任何存储设备。

Real Filesystems

正文: File Systems

尽早添加适当的文件系统支持是个好主意。

Graphics

正文: How do I set a graphics mode

真正的操作系统不是在基本文本模式下操作,而是有位图图形。 编写真正的图形驱动程序是一堆工作,尽管一些虚拟机提供了一些有用的快捷方式。

User Interface

Main articles: User Interface, Compositing

你肯定需要用你华丽的图形和可用的用户界面给操作系统开发社区留下深刻印象。

Networking

正文: Networking

网络支持的用途是显而易见的,所以你可能会想要这样做。

Sound

正文: Sound

声音是计算体验的重要组成部分,根据你的需求,你可能希望在通用硬件上支持声音。

Universal Serial Bus

正文: USB

如果你需要与现代外围设备通信,则可能需要USB堆栈并支持各种通用USB控制器。

第四阶段: 引导

你现在已经有了基本的操作系统,你已经准备好进入下一个层次。 在此阶段,我们将开始将软件移植到你的操作系统上,以便你可以自托管。 当你设置你的操作系统特定的工具链时,你已经开始努力自我托管,现在它有回报。

移植软件

正文: Cross-Porting Software

虽然并非所有软件都易于移植,但大多数Unix软件都带有autoconf生成的配置脚本。 你可以为这些脚本提供 -- host = mycpu-myos选项,如果你的操作系统提供了所需的功能,则可以将软件交叉编译到操作系统上。 你已经遇到了设置特定于操作系统的工具链时如何移植软件的示例。 虽然交叉编译软件的难度差异很大,但你将希望使用相同的过程来适应新的软件包。

移植GCC

正文: Porting GCC to your OS

当你设置操作系统特定的工具链时,你已经开始移植binutils和gcc的工作。 我们将完成该过程并将它们交叉编译到你的操作系统上,以便它可以编译C hello world程序。

在你的操作系统下编译你的操作系统

下一个任务是移植你的整个构建系统。 你可能需要移植GNU Make,移植一些命令行实用程序 (coreutils) 或编写自己的,移植真正的shell或完成你的操作等等。 你可能还需要修复操作系统中的许多错误,以便编译器正确运行。 你需要处理如何将新编译的版本转移到永久存储上,以便重新启动计算机将运行下一个版本。 你的操作系统现在将质量作为自编译。

完全自我托管

现在,你可以在你的操作系统下构建你的整个操作系统,你还需要能够完成其余的工作。 你需要能够在你的操作系统下构建你的编译器。 你需要能够在你的操作系统下进行开发,因此你将移植你最喜欢的文本编辑器或编写一个。 你需要联网,这样你就可以在互联网上发布最新版本 (建立在自己的基础上)。 你将移植大量的程序、库、游戏和任何你想要的其他东西,这样整个开发过程就可以在你的操作系统上进行。 你现在可以卸载原来的操作系统,并用新的亮闪闪操作系统替换它。

第五阶段: 获利

你现在已经成功创建了一个真正的操作系统,它是完全自托管的,是整个操作系统开发社区羡慕的。 你已经移植了quake,拥有OpenGL程序,可以正常工作的浏览器,蓬勃发展的贡献者社区,并取得了很大的成功。 你现在可以重新开始,从自己的操作系统开发下一个操作系统。