--开始之前的准备
一、导言
项目概述
在当今的计算设备中,操作系统(Operating System,简称 OS)扮演着至关重要的角色。它连接硬件与应用软件,管理资源,提供用户界面,是现代计算机和嵌入式设备正常运行的基石。随着 Arm64 架构的流行,我们越来越多地在移动设备、服务器以及物联网设备中见到这种高效且性能优越的处理器架构。
本文的目标是带领读者通过实践开发一个简单的裸机操作系统,能够运行在 Arm64 架构的设备上。裸机开发意味着不依赖于任何预先存在的操作系统或引导程序,直接与硬件打交道。这种低级别的开发方式有助于理解计算机系统的工作原理,是操作系统课程和嵌入式系统开发中的重要切入点。
通过本文,您将逐步学到如何初始化硬件、建立基本的操作系统功能模块,如内存管理、中断处理、设备驱动等,最后搭建一个基础的多任务操作系统。无论您是操作系统初学者还是希望深入了解 Arm64 架构的开发者,这份指南都将带给您丰富的知识和实用的技能。
本文后续的代码将基于下面的 github 项目,最终为该项目添加 arm64 的支持,后面文中省略的相关代码读者可以去 github 的项目中去查找。
目标读者
本文适合那些对计算机底层开发感兴趣、有一定编程经验的开发者们。特别是以下几类读者会从中受益:
- 操作系统课程的学生:若您正在学习操作系统课程,或者正在进行相关课程设计项目,这些内容将成为极好的参考和补充。
- 嵌入式系统开发者:如果您已经有一定的嵌入式开发经验但希望深入理解 Arm64 架构的细节,这份指南将提供有价值的实践示例。
- 计算机系统爱好者:对于希望了解计算机系统如何在底层运作的个人,本指南提供了循序渐进的实践方式。
您不需要具有 Arm64 的开发经验,但以下基础知识将会有很大的帮助: - C 语言和汇编语言:大部分代码将使用 C 语言编写,并会涉及一定程度的 Arm64 汇编。
- 计算机体系结构基础:理解寄存器、内存、输入输出等基本概念将大大有助于理解指南中的内容。
- 基本操作系统概念:调度、内存管理、中断等概念会在开发过程中频繁提到。
希望本指南能够启发您深入理解计算机系统,从而在未来的项目中更加游刃有余。让我们一起开始这段有趣且充满挑战的旅程吧!
二、预备知识
在开始开发 Arm64 裸机操作系统之前,掌握一些相关的预备知识和工具是至关重要的。本章节将简单介绍关于硬件、软件开发工具链以及基本概念的预备知识,帮助您准备好开发环境和理解核心原理。
硬件概述
Arm64 架构
ARM64,也称作 AArch64,是由 Ar m 公司开发的 64 位处理器架构。与传统的 32 位 Arm 架构(AArch32)相比,ARM64 在处理更多内存和更复杂的计算任务时有显著优势。以下是一些需要了解的关键点(这里只进行简单的概括,详细的介绍我们会在后续章节展开):
- 寄存器:ARM64 的核心寄存器组包括 31 个通用寄存器(x0-x30),每个寄存器均为 64 位。
- 指令集:AArch64 引入了一套全新的指令集,与 AArch32 相比,指令更加简洁和高效。
- 执行模式:ARM64 支持多个执行级别(EL0-EL3),用于不同的特权级别(例如:用户模式、内核模式、虚拟化模式和安全模式)。
开发环境搭建
本文使用的硬件环境将使用 qemu 来进行模拟,因此读者不需要单独准备硬件环境。后续的所有操作我们都将基于 ubuntu 和 qemu 进行。
开发工具链安装
为了编写和编译 Arm64 代码,您需要安装交叉编译工具链。以下是具体步骤:
GCC 工具链:ARM 公司和开源社群提供了 Arm64 的 GCC 交叉编译工具链。可以通过以下命令安装(以 Ubuntu 为例):
sudo apt-get install gcc-aarch64-linux-gnu
必要的软件
QEMU:QEMU 是一款开源仿真器,可以用于模拟 Arm64 的开发环境,非常适合在没有硬件设备时进行开发和测试。安装命令(以 Ubuntu 为例):
sudo apt-get install qemu qemu-system-arm
调试器(GDB):GDB 是一个强大的调试工具,可以与 QEMU 配合使用,安装命令(以 Ubuntu 为例):
sudo apt-get install gdb-multiarch=
编辑器(Virtual Studio Code):Virtual Studio Code 是微软开发的一款强大的开源编辑器,其以强大的可拓展性及丰富的插件生态而闻名。本文将借助 Virtual Studio Code 的调试功能来帮助我们使用图形界面来调试代码。
基本概念
这里只进行最简单的概念介绍,详细的介绍会在后面用到的时候展开
虚拟内存与物理内存
虚拟内存是操作系统使用的一种内存管理技术,使应用程序在不考虑物理内存实际限制的情况下运行。它允许每个进程拥有独立的地址空间,极大地促进了内存保护和多任务运行。
CPU 模式(EL0,EL1,EL2,EL3)
Arm64 架构支持多层次的执行级别(Execution Levels,ELs),每个级别具有不同的特权和访问权限:
- EL0:用户态,最低特权级,无法直接访问硬件。
- EL1:内核态,通常用于操作系统内核,具有较高特权。
- EL2:虚拟化层,支持虚拟机监控程序。
- EL3:安全态,用于安全监控程序,如 TrustZone。
异常处理(Exception Handling)
异常处理是操作系统的重要功能,用于捕捉和处理各种异常事件(如中断、陷阱、故障等)。理解 Arm64 架构下的异常类型及其处理机制是开发裸机操作系统的基础。
通过掌握以上预备知识和工具,您将具备开始开发 Arm64 裸机操作系统的基本条件。在接下来的章节中,我们将逐步进入实际的开发过程,从启动代码编写到内核功能实现,开启我们的实战之旅。
三、第一个裸机程序
在正式开始之前,我们将编写第一个裸机程序,通过最简单的操作验证我们所构建的开发环境,并了解 Arm64 系统启动的基本步骤。我们的目标是创建一个最小化的程序,能够在 Arm64 硬件上启动,并输出一个简单的信息(例如“Hello, World!”)。这是任何裸机开发的第一步,同时也是至关重要的一步,因为它验证了我们的工具链、硬件和基本配置的正确性。
目录结构
我们首先需要设置项目的目录结构,以便于管理代码和配置文件。本节使用的目录结构如下:
以上目录结构包含以下几部分:
- arch/:架构相关的代码
- arch/include/:架构相关头文件
- include/:公共头文件
- init/:初始化相关代码
- Makefile:构建脚本
- out/:存放编译生成的目标文件
启动代码
启动代码是裸机程序的起点,负责初始化硬件,设置堆栈,并跳转到 C 语言的内核主函数。我们将编写一个简单的启动文件 start.S
串口驱动
接下来,我们首先需要实现基本的 UART(串口)配置和输出函数,用于调试信息的输出。这里我们使用 qemu 模拟的串口设备(实际的硬件会更加复杂,这里仅仅是一个简单的 demo)。
链接脚本
为了将启动代码和内核代码正确地链接在一起,我们需要编写一个链接脚本 link.ld
构建与运行
最后,我们编写 Makefile 来简化构建过程
构建和运行程序
make clean
make run
在控制台执行上面的命令,这将使用 QEMU 模拟运行我们的裸机程序,并应在控制台输出“Hello World!”。
四、基础功能完善
为了方便后续的开发和调试,我们需要基于上一节的程序进行一些基础功能的完善。首先要完善的两点就是实现 printf 函数以及 debug 的支持。
添加 printf 函数
在开发操作系统的过程中,调试和输出信息是非常关键的操作。通过在控制台输出调试信息,我们可以跟踪程序的执行过程,诊断问题,确保系统按预期运行。因此我们将添加一个 printf 函数,用于输出格式化的字符串到串口控制台,就类似于 C 标准库的 printf 函数。
1.进行 bss 段初始化
由于后续的实现以及未来的代码必然会使用的全局变量,根据 C 语言的规范,未初始化的全局变量的初始值必须是 0,而未初始化的全局变量全部存在于 bss 段。所以,我们第一件要做的事就是在正式跳转到 main 函数之前,完成 bss 段的初始化,确保未初始化的全局变量的值是 0。基于上一章的内容,我们在 start.S 中添加如下代码:
在上面的代码中我们额外启动用了浮点数的支持,因为我们的部分代码编译后,编译器使用了 Q 系列的寄存器,不开启此功能会导致 CPU 陷入异常。
2.其他功能代码 其他功能代码的添加这里就不逐一介绍了,主要是 printf 函数的实现,具体的代码结构如下(这里只列举关键代码,详细的代码读者可以在 github 获取):
- 目录结构
- 关键代码
- main 函数
至此我们就完成了对 printf 函数的支持,后续就可以畅快的使用 printf 函数进行 log 输出了
添加 gdb 调试支持
在操作系统的开发过程中,调试是至关重要的一环。有效的调试手段可以帮助我们更好地理解程序的执行过程,快速定位和解决问题。GDB(GNU Debugger)是一款强大的调试工具,结合 QEMU 可以提供远程调试能力,使得我们能够在 Arm64 裸机环境下进行调试。在这一节中,我们将介绍如何在我们的裸机操作系统中添加 GDB 调试支持。
- 为 makefile 添加 run-gdb 目标
- 配置 vscode
为 vscode 添加 lunch.json
- 成果
五、总结
至此,我们正式开始之前的相关准备工作就已经完成,从后面开始,将正式开始我们的操作系统实现之路。下一篇我们将会从一个最简单的任务切换开始,逐步揭晓操作系统的面纱。
END
作者:Nick Hu
来源:OPPO内核工匠
推荐阅读
欢迎大家点赞留言,更多 Arm 技术文章动态请关注极术社区嵌入式客栈专栏欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。