【自制操作系统11】中场休息之细节是魔鬼

如果你有幸看到这一章,那么恭喜你,你已经完成了整个操作系统的一多半了,而且如果你前面的东西都完全掌握了,那后面无非就是顺水推舟的事情了。本章不做继续的讲解,而是将之前的知识进行回顾,并把相似的知识点做对比。同时我也将到目前为止最大的感悟 细节是魔鬼 分享给大家。

一、到目前为止的程序流程图

为了让大家清楚目前的程序进度,画了到目前为止的程序流程图,如下。其实就是截至到内存管理这一块

二、回顾一下我们都做了些什么

这里列出整个系列到目前为止的目录,刚好也可以作为索引方便大家阅读了

  第 01 和 02 部分没有实质性的代码,但却是学习一个新东西的必要开始,也就是解除困惑,梳理流程。它告诉了我们 计算机的启动过程,也就是计算机按下开机键之后,初始的程序计数器 IP 的值指向了哪里,初始执行的 BIOS 中写死的程序做了什么,又跳转到了哪里。这让我们至少拥有了能够写出一个让电脑按下开机键之后不报错并成功跳转到我们所写的代码的程序。之后的代码,就是在这两部分所创造的基本框架中添油加醋完成的。

  第 03 部分是 读取硬盘中的数据。我们所写的程序肯定是放在硬盘里的,需要加载到内存中才能被 CPU 一条一条取指令并执行。虽然 BIOS 帮我们完成了启动区的加载任务,但这只是很小的一部分,我们不能及期望于将操作系统所有代码都写到启动区这 512 字节中,所以启动区里的代码需要实现把更多在硬盘中的程序加载到内存中,这样一个关键任务。

  第 04 部分是 实模式到保护模式,这也是第一次 CPU 厂商和操作系统 打配合。我们只需要按照 CPU 要求的,比如 写好段描述符结构、加载 gdt、将 cr0 的 pe 位置 1 等,就可以顺利开启 CPU 的保护模式,利用其保护模式的特征了。

  第 05 部分是 开启内存分页机制,这又是一次 CPU 厂商和操作系统打配合的案例,也是按照 CPU 要求的步骤,把该有的数据结构(页目录表和页表)写好,就可以开启分页机制,利用其提供的分页特征了,由于打配合的案例越来越多,一会我单独总结。

  第 06 部分是我们 第一次使用 C 语言 来做事,也可以看出,之前用汇编语言把那些 杂事 都处理干净了,真正写内核主代码时,再把 C 语言请过来。我们学高级语言的人,包括我自己,都是认为越底层的语言越高端。不过从我们这个系列的角度看,汇编做的都是杂事,或者 C 语言不屑于做的事情,而 C 语言做的,才是“高大上”的事。所以学习这个系列,包括我自己写这个系列,也是让我从两个角度来审视这个问题了,也再也不会去争论到底高级语言高级,还是低级语言高级的事情了。

  第 07 部分是 深入浅出特权级,这部分也是没有代码。这部分就提到了我们常说的 内核态、用户态,只不过是从细节入手,讲述了特权级是怎么进行 保护、以及怎么进行 跳转 的。至于保护,自然有一套公式规则来判断,至于跳转,也是有一套跳转规则,也就是什么特权级,在什么情况下,能跳到什么特权级下。当然这只是简单的描述,实际情况要复杂得多。

  第 08 和 09 部分是 中断,从硬件讲到了软件,同时也指出了一个重要的思想,就是 操作系统是个死循环,是靠中断驱动 的,我们的操作系统就是随时等待着各种中断进来,然后执行相应的中断处理程序,为整个操作系统的运行方式做了个思想准备。

  第 10 部分是 内存管理系统,我们实现了简单的四个 内存池 的管理,并最终实现了一个 申请内核内存空间 的函数,该函数自动在内核的虚拟内存池中和物理内存池中找到可用的内存页,并将其映射到页表中。这让我们对内存管理有了个初步的认识。这块就不再需要更多的 CPU 配合操作系统的部分了(当然基础的都是需要的,我是说不再需要额外的),有点 纯软件设计 的感觉了,之前的部分或多或少都有跟硬件打交道的部分。我们慢慢地,将与硬件打交道的部分完善好,最后便只剩下软件的天下了,也是我们软件工程师越来越熟悉的部分。

  这也慢慢地,与我们的已有的知识接轨,什么时候全串起来了,你就是高手了。技术领域的高手,不是看的高望得远,而是基础扎实,但要扎实到随便把自己已有的知识进行关联,就能得出一个很深刻的结论。

三、CPU 与操作系统打配合

我们不只一次提到了 CPU 与操作系统打配合的地方,现在我们就一起来串一串,把之前这种配合写在一起对比一下。

配合项 操作步骤1 操作步骤2 操作步骤3
开启保护模式  打开 A20 加载 gdt 将 cr0 的 pe 位置 1
加载 gdt 内存某位置初始化全局描述符表 gdt lgdt 指令将 GDT 起始地址存入 gdtr 寄存器 将 cr0 的 pe 位置 1
开启分页 内存某位置初始化页表 pde、pte 将页目录起始地址存入 cr3 寄存器 将 cr0 的 pg 位置 1
开启中断 内存某位置初始化中断描述符表 idt,并初始化 pic lidt 指令将 idt 起始地址存入 idtr 寄存器  
特权级      

请自己默默体会其中的相似之处。

步骤相似,必然也存在着结构相似,下面我把到目前为止用到的结构列出

至于后面的内存管理池的结构,那是我们软件自己定义的,而上面列出的这些,是硬件定义的,也就是说作为程序员的我们,必须接受。

四、谈谈自己的理解与感悟

  这里我没有说谈谈自己对操作系统的理解,因为我觉得这里谈的可能超出了操作系统范畴。另外,我所谈的真的是 到目前为止 的理解与感悟,并不是我已经把后面的知识学完了再来补的,可能都学完了再回忆自己在这个时候的感悟,已经不准确了。

  高级语言与低级语言没有高下之分。我们普遍有个印象,就是外行人认为高级语言更高级,低级语言更低级,而内行人则相反。但我现在到觉得,它们根本没有高下之分,只是不同角度罢了。如果从功能上说,低级语言能完成高级语言做不了的事情,也可以解释高级语言无法解释的原理,从这点看,低级语言显得更高级。但如果从实际做的事情来看呢?本操作系统中,低级语言(也就是汇编)只是做了一些进入内核之前的杂事(当然一部分原因也是因为 c 语言做不了),一旦进入内核,只要能用 c 语言完成的,就绝对不用汇编了。从这个角度看,高级语言做的事情又比低级语言更高端一些。所以我的感悟就是,再也不去争论谁高谁低了,而只是说什么事情更适合什么语言来做而已。我觉得就单单是这个感悟,对我目前的 Java 语言帮助就很大,我不再觉得 Java 比 C 语言或是汇编语言更 low 了。

  细节是魔鬼。这真的是我最大的感悟,没有之一。我起初学习操作系统的时候,总是想尽快,想着有些东西只要理解就可以了,没必要去扣太多的细节。其实这是错误的,正确的做法是,先把细节扣得死死的,之后回过头看的时候就再也不看细节了,开始注重总结与理解。而不是先就不扣细节,想着总结与理解。第一点是因为,细节掌握得足够了,你会发现其他的好多知识点是通用的,根本不用看就可以理解了,比如 加载 gdt加载 idt以及加载分页,如果你不是在看加载 gdt 这个部分时把细节吃透,后面两个知识点你每个都要重新理解一遍,而且理解得还不一定透彻,所花的总时间,还不如你去花大量时间把第一个吃透,而后面两个非常快速地就可以理解到很深入的地步。

  越简单越透彻,越透彻越简单。这里的每一个知识点,我一开始都觉得比天都难,而在真正理解之后,却变得很简单,甚至有点无聊。你可能觉得这是废话,但有的时候,有些知识点我理解的糊里糊涂,理解得也很复杂,跟别人也说不明白,当时我觉得是知识点就很复杂,给被人讲肯定是讲不明白的,得人家自己去理解。但后来我发现,无论多复杂的事,只要你真正掌握并且抓到本质了,是真的很简单,甚至你可以给一个不搞技术的人讲明白(这个明白当然不是真正的懂哈)。就比如说内存管理这一块,我看的时候甚至一度要放弃,但后来经过对每一行代码,每一个结构都扣出来剖析之后,我竟然觉得这块简单得不要不要的,无非就是取一个虚拟地址,取一个物理地址,再把它们加到页表中对应起来。不过这块也同时说明了 细节是魔鬼。倘若你一开始就看到这句话,比如从某个一分钟搞懂操作系统的软文,你的理解就是“取一个虚拟地址,取一个物理地址,再把它们加到页表中对应起来”,和我扣完细节之后的理解一样,但你觉得这是真正的一样么?所以,不是因为它简单所以你理解的透彻,而是因为你理解的透彻,它就变得简单起来了。

  所以,细节真的是魔鬼,千万不要企图一篇文章就搞懂操作系统这种事,我也可以把这篇文章改编成一个类似的文章,但如果你不去花时间扣细节,你今后一定会把更多的时间耽误在这里的,这个账总会有一天找到你的头上。

写在最后:开源项目和课程规划

如果你对自制一个操作系统感兴趣,不妨跟随这个系列课程看下去,甚至加入我们,一起来开发。

参考书籍

《操作系统真相还原》这本书真的赞!强烈推荐

项目开源

项目开源地址:https://gitee.com/sunym1993/flashos

当你看到该文章时,代码可能已经比文章中的又多写了一些部分了。你可以通过提交记录历史来查看历史的代码,我会慢慢梳理提交历史以及项目说明文档,争取给每一课都准备一个可执行的代码。当然文章中的代码也是全的,采用复制粘贴的方式也是完全可以的。

如果你有兴趣加入这个自制操作系统的大军,也可以在留言区留下您的联系方式,或者在 gitee 私信我您的联系方式。

课程规划

本课程打算出系列课程,我写到哪觉得可以写成一篇文章了就写出来分享给大家,最终会完成一个功能全面的操作系统,我觉得这是最好的学习操作系统的方式了。所以中间遇到的各种坎也会写进去,如果你能持续跟进,跟着我一块写,必然会有很好的收货。即使没有,交个朋友也是好的哈哈。

目前的系列包括

微信公众号

  我要去阿里(woyaoquali)

原文地址:https://www.cnblogs.com/flashsun/p/12365967.html

时间: 2024-11-08 20:38:18

【自制操作系统11】中场休息之细节是魔鬼的相关文章

【自制操作系统12】熟悉而陌生的多线程

一.到目前为止的程序流程图 为了让大家清楚目前的程序进度,画了到目前为止的程序流程图,如下.红色部分是我们今天要实现的 二.进程与线程简述 相信看这篇文章的人,肯定不是对基本概念感兴趣,这也不是我的主要目的.所以这里真的是简述一下 进程和线程都是 独立的程序执行流,只不过进程有自己独立的内存空间,同一个进程里的线程共享内存空间,具体体现在 pcb 表中一个字段上,指向页表的地址值. 线程分 用户线程 和 内核线程,用户线程可以理解为就是没有线程,只是用户程序中写了一个线程调度器程序在假装切换,操

【自制操作系统14】实现键盘输入

一.到目前为止的程序流程图 为了让大家清楚目前的程序进度,画了到目前为止的程序流程图,如下.(红色部分就是我们今天要实现的) 二.简单打通键盘中断 既然要打通键盘中断,那必然需要你回顾一下 [自制操作系统08]中断 所讲述的外部中断的流程,下面我把图贴上. 如图所示,将上图中的某外部设备,换成下图中的具体的键盘,就是键盘中断流程啦.简单说就是: 因此每当有击键发生时,键盘中的设备 8048 会把键盘扫描码发给主板上的设备 8042. 8042 是按字节来处理的,每处理一个字节的扫描码后,将其存储

《30天自制操作系统》笔记(01)——hello bitzhuwei’s OS!

<30天自制操作系统>笔记(01)--hello bitzhuwei's OS! 最初的OS代码 1 ; hello-os 2 ; TAB=4 3 4 ORG 0x7c00 ; 指明程序的装载地址 5 6 ; 以下这段是标准FAT32格式软盘专用的代码 7 8 JMP entry 9 DB 0x90 10 DB "HELLOIPL" ; freeparam 启动区的名称可以是任意的字符串(8字节) 11 DW 512 ; 每个扇区(sector)的大小(必须为512字节)

【自制操作系统01】硬核讲解计算机的启动过程

目录 一.为什么是 BIOS 主导?    二.内存映射    三.实模式下的内存分布    四.怎么就从 BIOS 里的程序开始执行了    五.BIOS 里到底写了什么程序    六.0x7c00 是啥    七.启动区里的代码写了啥    八.操作系统内核写了啥        软硬件协同发展        历史遗留问题    九.参考资料    十.开源项目和课程规划        项目开源        课程规划 本讲只为讲明白下面一个问题: 我们按下开机键后究竟发生了什么? 好的,这似

《30天自制操作系统》读书笔记(2)hello, world

让系统跑起来 要写一个操作系统,我们首先要有一个储存系统的介质,原版书似乎是06年出版的,可惜那时候没有电脑,没想到作者用的还是软盘,现在的电脑谁有软驱?不得已我使用一张128M的SD卡来代替,而事实上你用的是U盘还是软盘对我们的操作系统没有影响,缺点是你的U盘刷入系统后容量只能是1440 MB,即当年流行的3.5英寸软盘的大小,当然不用担心,再格式化一次(用DiskGeniu),就可以恢复. 我做事情的话,总是怕自己的努力的结果白费了,害怕辛辛苦苦看完这本书但是发现做出来的东西现在根本没法用,

《30天自制操作系统》读书笔记(4) 绘图

暑假果然是滋生懒散的温床. (╯‵□′)╯︵┻━┻ 好久不动都忘记之前做到哪里了, 上次好像做到了C语言的引入, 这一节所做的东西都相当轻松, 将会绘制出操作系统的基本界面. 绘图的原理 按照书中所说, 将值写入到显存中就能在屏幕上显示相应的像素, 在asmhead.nas 中有这一段: 1 CYLS EQU 0x0ff0 ; 设定启动区 2 LEDS EQU 0x0ff1 3 VMODE EQU 0x0ff2 ; 关于颜色数目的信息,颜色的位数 4 SCRNX EQU 0x0ff4 ; 分辨率

《30天自制操作系统》笔记(12)——多任务入门

<30天自制操作系统>笔记(12)——多任务入门 进度回顾 上一篇介绍了设置显示器高分辨率的方法.本篇讲一下操作系统实现多任务的方法. 什么是多任务 对程序员来说,也许这是废话,不过还是说清楚比较好. 多任务就是让电脑同时运行多个程序(如一边写代码一边听音乐一边下载电影). 电脑的CPU只有固定有限的那么一个或几个,不可能真的同时运行多个程序.所以就用近似的方式,让多个程序轮换着运行.当轮换速度够快(0.01秒),给人的感觉就是"同时"运行了. 多任务之不实用版 我们首先从

20天自制操作系统(一)

为什么博文分类以及博文名字叫"20天自制操作系统"呢? 因为6月11日到7月还有接近20天的时间,所以我取整,接近20天内学完. <30天自制操作系统> 作者  川合秀实   译者  周自恒,李黎明,曾箱江,张文旭 这本书. PS:从5月20号到6月10日,除了上班之外,下班就是吃喝玩,浪费了特别多的时间.看到BIT祝威日进千里,我深感惭愧.所以我决定"改邪归正". 好了,开始. 首先罗列出工具: ----------------------------

&lt;&lt;30天自制操作系统&gt;&gt;(1)初体验汇编程序

我们这次使用的汇编语言编译器是原书作者自己开发的,名为“nask”,很多语法和著名的汇编语言编译器nasm很像.由于原书作者没有给出有哪些不同,这里就无法给出不同了! 现在仅仅使用汇编语言中的DB指令来写个“操作系统”吧. DB指令是"define byte"的缩写,往文件里写入1个字节 超长的源代码 1 DB 0xeb, 0x4e, 0x90, 0x48, 0x45, 0x4c, 0x4c, 0x4f 2 DB 0x49, 0x50, 0x4c, 0x00, 0x02, 0x01,