文章目录
- 前言
- 操作系统基本概述
- 中断
- 与硬件的基本交互
- 基本地址
- 地址概念
- 启动流程
- 应用程序与操作系统的关系
- Hello World启动
- 总结
前言
本系列博文主要用于第二阶段深入了解的408专业内容考研使用。也就是说在开启本系列之前,最好已经对408有基本的了解。重复的基础概念将不在重复,此外,本系列博文,将同时虽然本系列位操作系统学习系列,但是同时会完成C语言程序设计与数据结构的复习运用。
本系列将结合王道考研为大纲导航,结合《30天自制操作系统》等优秀图书,一步一步将书中的内容进行巩固并使用汇编和C语言完成简单的操作系统设计。在本系列当中,博主本人也就在不断记录学习过程当中的内容,因此在系列结束之前,可能还会有很多不准确的部分,请见谅!
此外,本文也是需要基于Intel CPU完成操作,AMD 在这里 no.
操作系统基本概述
那么在开始之前,我们先介绍了一下基本的操作系统的概念。首先的话,我们需要明确操作系统为我们提供了什么东西。
首先操作系统为我们提供了几个基本的管理:
- 内存管理
- 设备管理
- 文件管理
- 处理机管理
同时我们知道,操作系统有几个基本的特性:
- 并发
- 异步
- 虚拟
- 共享
如果,没记错的,这个应该就是王道考研里面第一章节的内容。这里我就不多说了,书上比我讲得更加详细。
那么在这里我更多的是想要做补充。
中断
操作系统为我提供了程序接口,这个程序接口是由一系列的系统调用构成的,同时对于系统调用,例如读写文件,这个时候,还会触发中断,进行IO操作。这个都是第一章节的内容,我们都知道,为什么会触发中断,是因为,这个IO操作是进行了系统级别的,内核级别的调用。那么实际上的话,流程是正确的,但是这个部分的实现其实是非常重要的一个基础。在后面进行实际实现操作系统的细节的时候,我们将经常提到实模式和保护模型。但是这里关于中断的话,我们先不管不管那么多,我只是想说明,这个中断是非常重要的一个机制之一。
此外,值得一提的是,中断是在硬件层次上也是支持的。对于Ring0,1,3 当中这个其实在CPU当中是支持的。在我们的这个保护模式下面,我们通过DRT将实现对这部分的处理。
与硬件的基本交互
还是那句话,在阅读本文之前,我们期望你已经对操作系统有了大致了解,在这里也确实推荐王道考研的操作系统,虽然偏向刷题,但是有些概念解释的还是很不错的,至于其他的是这个系列的博文要描述的,这里再次声明。
通过计算机组成原理我们知道,对于CPU而言,他里面有ALU,CU,运算和逻辑控制单元。同时内部还有很多的寄存器。例如常见的八个寄存器:
AX: 累加寄存器
BX: 基地寄存器
CX:计数寄存器
DX:数据寄存器
SP: 栈针寄存器
BP: 基栈寄存器
SI: 源地址寄存器
DI: 目标地址寄存器
CS: 状态寄存器
(注意,这里的几个寄存器是2个字节的,同时这个是在实模式下面使用的。实模式下面是16位的,在保护模式下面是32位的)
当然在CPU当中还有很多寄存器。同时,在这里有一个非常重要的概念,我们需要粗暴的知道。在计算机组成原理里面我们知道,对于不同的设备我们都是有编址的。我们对不同设备的操作,其实是通过改变这些地址里面的值来完成的,也就是说,我们通过寄存器,来访问地址,操作地址的值,我们就可以完成对基本设备的控制。
当然这里我们需要明确的一点就是。我们在这里面大部分的编程工作是通过控制CPU来完成的。当我们需要控制,例如键盘,屏幕的时候,是通过寄存器,修改里面的数据来控制的。所以说,当我们在初期实现的时候,需要和汇编进行一定的交互,已完成对硬件的基本控制。当然这里值得庆幸的是,硬件厂商提供了良好的接口,或者说是Intel和硬件厂商有良好的约定。
基本地址
前面我们刚刚说到,那就是,我们通过CPU完成基本的程序控制,同时,我们通过找到设备地址,然后通过寄存器操作里面对应的值来完成对设备的控制(接下来我们举一个输出Hello World的例子)
所以,在这里,我们明确一个概念,那就是,计算机的本质其实就是对不同位置的数据进行不同的操作罢了。只是我们通过不同的规定,让计算机呈现出缤纷多彩的世界。比如,一个exe文件是一串二进制代码,一个jpg图片也是,但是他们的效果完全不同。
因此,我们明确了地址的重要性,同时,对于设备也是类似的,设备也有地址,如前面说到,我们要控制他们就需要通过寄存器操作,而寄存器里面有那个地址,或者数据。因此,为了能正常调用设备,我们还需要约定一些地址。
比如这个:
地址概念
之后是地址的概念,其实在我们的操作系统当中,所使用的都是逻辑地址,一个程序的执行,我们从物理地址,拉取到数据,然后放在内存当中,在操作系统当中有很重要的一点,那就是,我们需要让应用程序,认为他是在是独占CPU的,从逻辑地址0到逻辑地址100,假设有一个程序是这样写的,那么实际上在物理上他可能是从0x6000 - 0x6545 等等。所以的话,很多考题有一个地址换算的题目。 同时我们还要知道,cpu在运算的时候呢,我们是使用二进制的,但是在操作系统表示的时候呢,我们使用的是16进制。16进制有个好处,第一它可以很容易表示十进制里面很大的数,同时不会浪费太多的空间,之后,16进制转换2进制非常方便。
此外这里再次强调了,我们需要先阅读王道考研的操作系统书本,对它有个基本了解,因为,我们这边其实是和王道考研里面的内容不一样的。实际上,我们需要先从磁盘开始,从磁盘拉取到我们的程序,然后加载,等等,直到我们的操作系统当中需要处理程序的时候,我们需要考虑到,多道程序的设计,并发,共享。经常考的pv操作,置换算法,轮换算法等等。
启动流程
这个应该就是在王道考研当中,第一章的内容。接下来我们先简单介绍一下。
首先,在启动的时候,我们会启动Bios,在bios里面我们会找到操作系统Boot下面的mbr,然后通过mbr,去加载到我们的loader程序,之后通过loader去加载到系统内核。那么mbr就是我们的一个引导。通过,引导,我们将完成后续的操作。那么问题来了,为什么我们要先mbr->loader->keneral 原因很简单,在bios里面,给我们的空间只有512byte,这显然不够一个系统的启动,内核的启动。
所以我们需要通过这个流程完成启动操作。
他们的大概流程其实就是这样的:
这个过程当中,我们将cpu的执行转移到了操作系统
应用程序与操作系统的关系
很好,终于到了这一个我需要补充的概念了。
我们直到,一个程序,例如这段程序。
#include<stdio.h>
int main(){
printf("Hello world");
return 0;
}
我们可以将,这段代码编程可执行文件.exe在底层的时候是翻译为bin二进制文件进行执行的。.exe文件将可以在windows系统当中执行。
那么实际上,我们知道,操作系统其实本质上就是一个特殊的软件,那么如果我们写的软件,也可以放在BIOS启动的时候,cpu的执行转移到我们的程序上,那么是不是也意味着,我们的软件也可以和操作系统一样。实际上,这个叫特殊的”操作系统“也是可以的。但是,实际上的情况是,我们启动软件,还是通过操作系统完成的,而不是刚刚说到,如果是刚刚说的那个样子的话,那么操作系统似乎也没啥作用了。
那么实际上一个程序完整的程序(win)是这样的:
所以说,我们如果想要实现一下我们的操作系统的话,我们必须要提供对应的程序依赖接口,是的,我们还需要定义我们的操作系统的可执行文件。这个其实和浏览器很想,我们的一个个程序,其实相当于一个个网页,网页里面的程序需要依赖浏览器展示效果,通过v8引擎完成解析。同样的我们的操作系统也是一样的。
那么回到我们刚刚的程序。
我们通过C语言实现输出”Hello Word“ 是如此简单。
实际上,我们是调用了 stdio.h 相当于python的包是吧,它里面提供了输出的函数,而输入输出,我们知道这个是需要系统调用的,因此,我们操作系统层面是需要实现的。因为,应用程序,是没有这个权限的,只有我们操作系统有。
那么如果我们要从屏幕上输出一句话,我们在底层实现是很麻烦的,同时,在实现的时候,我们不能调用任何系统实现,也就是printf() 这种函数,而是需要通过汇编实现类似这一的代码:
(是的这个就是我们前面说的输出内容,我们找到了xb800,这个是平面显示器的地址)
mov ax,0xb800 ;在bios当中将指针指向文本显示地方
mov es,ax
mov byte [es:0x00],'L' ;找到的文本显示的地址,然后写入内容
mov byte [es:0x01], 0x07 ;设置颜色
mov byte [es:0x02],'Y'
mov byte [es:0x03], 0x06
time 510 - ($-$$) db 0 ;填充剩下的空间,引导区是512
dw 0xaa55 ;以这个结尾才会别biso识别
Hello World启动
很好,我们补充完了和王道不太一样的内容。当然这里遗憾的是受限于篇幅,这里对应汇编部分的代码不进行讲解。但是《30天自制操作系统》这本书上对应汇编的解释我觉得非常棒,虽然那本书上使用的是ask汇编,其实那也是nasm自定义版本,大体上是一致的和汇编。
那么现在,我们开始第一个hello word ,这里的话,我们就不按照书上的来了,而是使用类似方案 。
首先,我们开始编写第一个启动程序,这个就是我们的mbr .
org 07c00h
mov ax,cs
mov ds,ax
mov es,ax
call DD
jmp $
DD:
mov ax,BOOTMSG
mov bp,ax
mov cx,16
mov ax,01301h
mov bx,000ch
mov dl,0
int 10h
ret
BOOTMSG: db "hello, OS World!"
times 510-($-$$) db 0
dw 0xaa55
然后,此时我们需要将这段代码进行编译。
再次之前你需要自己准备好nasm
此时我们完成了编译。之后我们还需要创建一个虚拟硬盘,接下来我们将在虚拟机上启动。
之后的话,我们将”第一个操作系统“写入到磁盘当中。
之后我们创建虚拟机即可,我这里使用的是virtual Box
之后点击启动,即可完成第一个Hello OS World
总结
本文只是作为,一个博主的随笔,后期才会进行完整的补充,当然,实际上,对应考研党而言,刷题更加重要,这个作为实操加分项。此外,博主默认,读者与博主水平类似。