2KB项目,专业的源码交易网站 帮助 收藏 每日签到

用 C/C++ 写一个 16 位的虚拟内核

  • 时间:2019-01-23 18:37 编辑:2KB 来源:2KB.COM 阅读:316
  • 扫一扫,手机访问
  • 分享
摘要:
C/C++ 英文原文:Writing a 16-bit dummy kernel in C/C++

前言

在前一篇文档,我只是简要地介绍了如何编写引导装载程序。做这件事令人开心,同时也具有挑战性。我非常乐意做这件事。在我了解了如何编写引导装载程序后,我想编写更好的功能,比如向引导装载程序中嵌入更多功能。然而,这么做的话引导装载程序的大小就会逐渐地增长,会超出512个字节。这样,每次从引导盘重新启动系统的时候,我都可以看到这样的错误提示:“这张盘不是系统引导盘”。

这篇文档的描述范围

我将在这篇文档简要介绍引导装载程序所在的文件系统的重要性,然后再编写一个虚拟内核,这个虚拟内核除了以文本的形式提示用户输入之外再没有其他功能。为什么我要把引导程序存储在FAT格式的软盘呢?这么做能给我带来哪些好处呢?由于这篇文章太短无法详细的说明文件系统,所以我将尽可能简短地说明文件系统内容。

基本说明

  • 如果你之前有任何编程语言的经验,那么这篇文章将会给你提供一些帮助。虽然这篇文章是一个简单的介绍,但是使用C或者汇编写引导程序仍旧是一个艰巨的任务。如果你是一个写程序的新手,那么我建议你读一下如何写程序以及介绍电脑的基本知识的教程,然后你再来阅读这篇文章。

  • 通过这篇文章,我将向你介绍各种与电脑有关的问题和回答的相关术语。坦白说,我写下这篇文章就好像我正在介绍这篇文章给我自己。所以许多的问题和回答尽力做到像谈话的方式,以便在我每天生活之中就能够明白它的重要与目的。例如:计算机是什么意思?或者为什么我需要它们因为我比它们更聪明?

你可以翻阅我之前的文章以便学习如何使用汇编和C写一个boot-loader。

这里是一些链接:

http://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part
http://www.codeproject.com/Articles/668422/Writing-a-boot-loader-in-Assembly-and-C-Part

如何组织内容?

这是这篇文章的主题。

  • Boot-loader 限制

  • 从boot-loader调用磁盘上的文件

  • FAT 文件系统

  • FAT 工作流程

  • 写一个 FAT boot-loader

  • 写一个16-bit的虚拟内核

其它翻译版本 (1) 加载中

Boot-loader 限制

在以前的文章中,我试图编写 boot-loader,在打印出一些带颜色的矩形后,我想在其中嵌入更多的功能。但是,对我而言,512 字节是个极大的限制,无法更改 boot-loader 的代码来做更多的事情。。。

挑战如下:

  • 按照功能嵌入更多的代码到 boot-loader 中

  • 限制 boot-loader 的大小为仅有的 512 字节

我如何来处理上述问题?

简述如下。

第 1 部分:

  • 我会用 C 语言写一个叫做 kernel.c 的程序,确保我期望的其它全部功能都正确的在其中实现。

  • 编译,并将执行程序保存为 kernel.bin。

  • 现在,拷贝 kernel.bin 文件到启动盘的第二扇区中。

第 2 部分:

在我们的 boot-loader 中,所有我们能做的是 加载 启动盘的第二扇区(kernel.bin)到内存的 0x1000 地址处,然后从 0x7c00 跳转到 0x1000 地址处,开始执行 kernel.bin 文件。

下图供您参考,可以了解一下。

从 bootloader 调用磁盘上的其它文件

之前,我们逐渐意识到,我们可以从 bootloader(0x7c00地址)将控制跳转到其它地方,如磁盘文件 kernel.bin 加载到内存中的地址,然后继续执行。但我心中还有几个疑问。

你知道kernel.bin在磁盘上占用多少扇区吗?

这很容易。我们要做的是以下这些

1扇区=512bytes

因此,如果kernel.bin的大小是512 bytes,它将占用1个扇区,如果是1024 bytes,那么它将占用两个扇区,等等...

现在,指针是建立在kernel.bin文件大小的基础上,在boot-loader中,你必须硬编码一定数量的扇区以便读取kernel.bin文件(译者注:所谓的硬编码指指将可变变量用一个固定值来代替的方法,但是采用这种方式之后,如果以后需要更改此变量就非常困难了,比如 if(a==2)就是硬编码,而 if(a==b)就不是硬编码)

考虑到将来,你想要通过频繁的更新内核来升级内核,你必须在引导中写个小笔记纪录kenrl.bin文件的占用扇区,否则内核会崩溃。

你是否想过想要加入更多除了kernel.bin的文件,

比如 添加office.bin,entertainment.bin,drivers.bin到你内核中?

在某种程度上是这样的,你要做的就是添加一个一个的文件到你软盘中,在这个过程中,你必须保证在引导盘中,每个文件都在其正确的位置,而且每个文件都会占据一定的扇区或者很多扇区。

但有点我想要你注意,系统将会变得越来越复杂,但我非常喜欢这样做。

你是怎么知道添加到boot-sector的一个一个文件是你需要的?

我们做的是从boot-loader加载各自的扇区程序到内存中然后开始执行它。但是这非常的不完美,一些东西将会丢失。

丢失了什么?

我认为boot-loader盲目地加载扇区的一个一个程序文件,然后执行文件。但即使在boot-loader尝试加载文件到内存之前,应该要检查文件是否存在在引导盘中。

会发生什么如果我错误的复制一个错误的文件到两个扇区到boot-loader中,然后更新boot-loader,之后运行它?

我的系统仅仅会崩溃,我的用户会抛弃我的系统,因为这不是他们想要的结果。所以,在这种情况下我们需要在引导盘中有固定的位置,所有的文件写成书中的索引。

我的boot-loader会执行软盘中索引以便寻找文件,如果文件名在索引中被列出来的话,然后继续加载文件到内存中。

哇!!! 这非常的棒,它为我节省了大量的步骤。

这回避免一些问题,因为早期的boot-loader常常盲目地加载扇区程序,然后硬编码它。

为什么你要加载这个文件,如果你不知道文件是否被正确加载?

怎样解决?

我们所需要做的是在磁盘上组织上面所列的信息,之后开始组织这些数据,并重新编写 boot-loader,以便它可以真正有效的加载文件。

这种大规模组织数据的方式被认为是文件系统。存在许多类型的文件系统,不管是商业的还是免费的。我在下面列出其中的一些。

  • FAT

  • FAT16

  • FAT32

  • NTFS

  • EXT

  • EXT2

  • EXT3

  • EXT4

FAT 文件系统

在我介绍文件系统前,有些技术点是你需要知道的。

在 FAT 文件系统中,一个簇占据了一个扇区,一个扇区在存储介质上占用了 512 字节。所以,在用 FAT 格式化过的磁盘上,1个簇等于1个扇区。

在 FAT 文件系统上,簇和扇区是最小的单位。

为了方便使用,FAT 文件系统被划分为四大部分,如下所示。

  • 引导扇区

  • 文件分配表

  • 根目录

  • 数据区

我尽可能以图片的形式展示给你,以便更好的理解它。

现在让我们简单描述一下每个部分。

其它翻译版本 (1) 加载中

引导扇区(Boot Sector):

在 FAT 格式的磁盘上,引导扇区中写有与 FAT 相关的信息;因此每次磁盘加载到系统时,操作系统都能自动获取到它的文件系统信息。

操作系统读取 FAT 格式磁盘的引导扇区,解析出所需信息,然后识别出文件系统的类型,据此读取文件内容。

写在引导扇区中的 FAT 文件系统信息称为启动参数块(Boot Parameter Block)。

启动参数块:

让我来带您看看,引导扇区的启动参数块里都有哪些值吧:

文件分配表(FAT表):

文件分配表实际是一个单链表,结点中存有文件的下一个簇值(cluster value)。

FAT 中的簇值有两种用途。

  • 标记文件的结束

    • 如果簇值在 0x0ff8 到 0x0fff 之间,则说明文件不再有别的数据块了(达到文件末尾EOF )。

  • 标记文件数据所在的下一个扇区

注:

我在图中提到了两张 FAT 表,表1和表2。你需要记住的就是,一张表是另一张表的拷贝。一旦一张表的数据丢失或损坏,另一张表的数据可以作为备份。这就是使用两张表而不是一张表的唯一原因。

根目录(Root Directory):

根目录可以看作磁盘上所有文件名的索引。所以 bootloader 会从根目录中查找文件名,如果能找到,就能从根目录中得到文件的第一个簇,并据此加载数据。

bootloader 从根目录中找到文件的第一个簇之后,会从 FAT 表中查找文件的下一个簇,直至达到文件末尾EOF。

数据区:

这是实际存放文件数据的区域。

一旦程序能识别相应的扇区,就可以从数据区中提取出文件的数据。

FAT 流程图

举个例子,假设 boot-loader 需要把 kernel.bin 文件加载到内存中,然后运行。要完成这个任务,我们只需为 boot-loader 编写以下的功能。

将根目录表中,从偏移量为0的位置开始的前11字节数据与 "kernel.bin" 这个字符串相比较。

如果能匹配这个字符串,则从根目录表中偏移量为26的位置提取 "kernel.bin" 文件的第一个簇。

现在我们已经得到 "kernel.bin" 文件的起始簇了。

只需将簇值转化为对应的扇区,然后把数据加载入内存。

在找到 "kernel.bin" 文件的第一个扇区并载入内存后,再从文件分配表(FAT表)中查找文件的下一个簇,检查是否还有剩余数据,或是已经到达文件末尾。

整个流程可以参考下图。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。


2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部