本文是JackOS开发日记的第1篇,记录了最近几日的开发情况,并且介绍了开发工具链,以及JackOS预期达到的目标
JackOS开发日记 1:最近的进度以及开发工具链和目标成果
暑假的前一段时间因为要去申请一下签证,所以去了广州一趟,不过开发并没有落下。
1.最近的进度
最近学习了硬盘的物理结构,虽然磁盘的物理结构其实在学校讲的操作系统这门课上讲到外存管理的时候老师上课讲过了,但是我觉得当时的学习更多的是机械式的记忆,即记住了磁盘的物理结构,并没有理解磁盘的物理结构。
但是这一次,在了解了磁盘结构(传统的柱面/磁道/扇区)的基础上,我又学习了放在第0柱面、第0磁道、第1扇区的主引导记录(Master Boot Record,MBR),主引导记录负责计算机的启动。磁盘在计算机看来其实就是二进制的序列,我们可以把我们的数据和程序写入其中,因为数据和程序本质上来说都是二进制序列。所以对于MBR这个第一个分区来说,我们既可以把数据写入其中,也可以把程序写入其中。但是更一般的,我们会把程序写入第一个分区,即MBR分区中,具体原因就是因为MBR负责计算机的启动。
具体来说,主板上的BIOS程序放在ROM芯片上,开机之后就会运行ROM里的BIOS程序(CPU初始化后CS:IP被强制加载到1M内存的最后16个字节,后16个字节其实是一个绝对跳转指令jmp far
,跳转的目的地址是BIOS程序);而BIOS程序在完成了开机硬件自检、中断向量表IVT的设置之后,就会去读取每个磁盘的第0柱面、第0磁道、第1扇区,如果找到了程序,那么就会运行其中的程序。因此我们就需要MBR分区中写入可以运行的程序,MBR中的程序会从磁盘中读取新的程序运行,就这样运行起来了操作系统。
虽然说启动扇区是CHS模式下的概念,目前都是固态硬盘了,基本用的都是LBA,但是第一个扇区的这个概念依旧存在。因此MBR这种传统的启动方式还是OK的。现代都是UEFI了,那就是以后在学的东西了。
目前,我已经写出了自己的MBR程序,这个MBR程序会去读取磁盘中的程序(BootLoader),然后去运行该程序(BootLoader)。
工欲善其事,必先利其器
2. 开发工具链
开发操作系统时,当然需要掌握开发用到的各种工具,形成自己的开发工具链。然后再介绍一下JackOS的预期目标,这样就可以正式的开始开发了。
开发操作系统中会用到很多的工具,主要分成下面几大类:
虚拟机
VirtualBox
:实体机仿真bochs
:调试代码用
二进制文件查看以及读写:
xxd
:主要用于查看小段硬盘镜像dd
:主要用于写入启动扇区wxhexeditor
:WinHex的Linux版本,集查看、修改于一体bximage
:硬盘镜像操作工具
编译器:
nasm
:汇编语言编译器gcc
:C语言编译器
而在开发的时候,工作流程是这样的:
首先通过VsCode写好
.asm
和.c
的汇编和C语言源代码接下来通过
nasm
和gcc
分别对汇编和C语言源代码进行编译对于汇编来说,开发操作系统时候,编译的
asm
文件有两种去路:- 要么通过
nasm
编译得到bin
格式的裸二进制指令文件。裸二进制指令文件里直接就是二进制的CPU指令,CPU可以直接运行,不需要操作系统环境。所以裸二进制的bin文件,主要就是在计算机开机时候直接执行,用于拉起来操作系统 - 要么通过
nasm
编译得到obj
格式的共享文件,用于与C语言进行混合编程。更加形象的说,就是用汇编为C开发最基础的库函数。因为只有汇编才可以和硬件进行直接的沟通,而完成如读取硬盘、显示文字等功能其实就是和硬件进行沟通,所以必须是用汇编来实现这些功能。而后C语言调用汇编来完成这些功能。具体来说C和汇编的混合编程有两种,一种是C的内联汇编,另外一种就是汇编和C分别编译成obj文件后链接在一起。
- 要么通过
对于C来说,开发操作系统的时候,最基本的一些功能必须要用汇编来实现,但是在用汇编完成了这些工作之后,就用C语言调用汇编来执行这些功能,因此在此之后,就利用C来完成系统内核的开发。
最终编译的结果有两种:
- 一种是裸二进制bin格式程序:上面说了,这种程序/文件里面直接就是CPU指令,CPU可以直接执行,所以主要是在开机启动阶段运行
- 一种是正常的可执行程序:未来编译出来的内核其实就是一个可执行程序。可执行程序在裸二进制程序的基础上,添加了描述程序的信息,加在裸二进制代码前。这样做的好处就是由于我们有了程序的其他信息,方便了我们去运行程序。关于这个未来会详细解释。
在编译后得到了可执行程序,我们把可执行程序(即操作系统)写入到磁盘映像文件。磁盘映像文件其实就相当于磁盘。我们真实的计算机开机之后,操作系统从磁盘中启动,而我们用虚拟机来调试的话,因为磁盘映像文件相当于磁盘,所以虚拟机中的操作系统就从磁盘映像文件中启动。关于磁盘映像文件,未来会进行详细的解释。
最后,我们在虚拟机中启动我们的系统,利用bochs进行单步调试,VirtualBox进行实体机仿真
上面就是我们正常的开发操作系统内核时候的工作流程。其实最后还有一步,就是把我们写好的系统烧录到U盘上,从U盘上启动我们的操作系统。不过关于这一步,我目前还只是设想,因为当前的计算机启动用的基本都是UEFI,而为了关注于开发操作系统,我像用传统的BIOS开发来引导操作系统,所以其实我们最后的系统能否从U盘启动还是有些问题的。不过关于这个问题,后面开发到了再说吧。
而关于具体怎么使用这些工具,我想未来我会专门写一系列博客来介绍,毕竟在这篇文章中介绍这些工具的话,一个是介绍不完,另一个是会导致这篇文章偏离方向。
3. 目标成果
介绍完了开发工具链之后,接下来就要对JackOS进行一下规划了。目前我对JackOS的规划是这样的(当然,不排除未来随着开发的逐渐深入/对内核开发逐渐深入会改变规划):
- 运行在32位保护模式下,16位实模式的话难以做到虚拟内存,而64位又有些复杂,所以折中考虑,还是写一个32位保护模式的系统
- 运行在字符模式下,主要是为了避免图形模式需要对字符进行渲染,增加复杂度。因为我本身对计算机图形学没有很多的了解,未来给写好的系统做窗口模块的话可能会考虑。
- 类Unix的非实时操作系统,因为我参考的几本书都是类Unix的书:赵炯老师的《Linux内核完全剖析》、郑刚老师的《操作系统真相还原》,还有荷兰神仙Tanenbaum教授的《操作系统:设计与实现》的MINIX系统和《现代操作系统》
具有操作系统最基本的功能:
- 进程与线程实现:进程与线程实现、CPU调度、同步与互斥、死锁检测与解除
- 内存管理:基本段/页式内存管理、虚拟内存实现
- 文件系统:FAT文件系统、EXT2文件系统,NTFS文件系统、虚拟文件系统
- I/O管理:可以连接一些外部设备
- 未来可能考虑转UEFI开发,这样就可以把真实的在实体机上跑我的操作系统。
当然,我知道这个目标很大,但是万事开头难,坚持下去一定会有成果。目标有点大,我忍一下~