跟我一起写操作系统(一)——10分钟写个操作系统

转载注明出处: http://www.cnblogs.com/lucasysfeng/p/4846119.html

  项目地址:https://github.com/lucasysfeng/lucasOS

 

  想动手,但不知从何入手,是学习一门新知识普遍会遇到的尴尬点。笔者喜欢边实践边学习理论,笔者的写作思路是:入门的文章要避免讲一些高深的理论,而应该先抛出demo,从研究demo入手,逐步加深demo的难度,从而学习这个过程中涉及到的理论知识。下面就让我们花10分钟写个“操作系统”。

第一节 开发环境


  我们在linux下制作软盘、编译内核等,因此需要linux开发环境。如果你用windows, 那么在windows下安装VMware, 在VMware中安装ubuntu虚拟机,此ubuntu作为开发环境。

  注:笔者的开发环境是windows--VMware--ubuntu14.04.

第二节 计算机启动过程


  写操作系统看似是一个复杂的过程,但只要我们将过程分解,完成每一步,那么完成一个操作系统就是水到渠成的事了。好了,我们就看一下计算机的启动过程,看操作系统何时被启动的。

  第一步:读取BIOS

  按下电源按钮后,计算机首先读取一块ROM芯片,这块芯片里的程序是"基本输入输出系統"(Basic Input/Output System),即BIOS.

  第二步:硬件自检 

  BIOS会检查计算机硬件是否满足运行条件,如果硬件出现问题,主板会发出不同含义的蜂鸣,启动中止。

  第三步:启动顺序

  硬件检查完成后,BIOS会将控制权交给下一阶段的启动程序,注意,“下一阶段的启动程序”可能存放在硬盘中,也可能存放在CD/DVD中,或者软盘中等等,可以设置BIOS选择从哪个设备启动

  第四步:主引导记录

  BIOS找到了“下一阶段的启动程序”所在设备,会读取该设备的第一个扇区,即读取最前面的512字节,称为主引导记录。主引导记录会告诉计算机下一步到哪里去找操作系统。

  第五步:bootloader

  计算机读取"主引导记录"前面446字节的机器码之后,运行事先安装的“启动管理器”bootloader,由用户选择启动哪个操作系统。如果你安装了多个操作系统,那么就要从这步做出选择了。

  第六步:加载内核

  好了,选择操作系统(内核)后,会加载内核,下面就交给内核去处理了。

第三节 主引导记录


   我们使用虚拟机来启动操作系统,上面的第一步和第二步我们不做,由虚拟机去完成;第三步“启动顺序”我们选择从软盘启动(我们用镜像代替,并不是真的软盘),需要对虚拟机做下设置,选择从软盘启动。下面重点来看第四步,我们写一下“主引导记录”,让BIOS读取我们写的主引导记录。

   1. 主引导记录代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
; 文件名 boot.asm
 
org 7c00h                     ; BIOS读入MBR后,从0x7c00h处开始执行
 
; 下面部分和10h有关中断,10h中断用来显示字符
mov ax, cs
mov es, ax
mov ax, msg
mov bp, ax                    ; ES:BP表示显示字符串的地址
mov cx, msgLen                ; CX存字符长度
mov ax, 1301h                 ; AH=13h表示向TTY显示字符,AL=01h表示显示方式(字符串是否包含显示属性,01h表示不包含)
mov bx, 000fh                 ; BH=00h表示页号,BL=0fh表示颜色
mov dl, 0                     ; 列
int 10h
  
msg: db "hello world, welcome to OS!"
msgLen: equ $ - msg           ; 字符串长度
times 510 - ($ - $$) db 0     ; 填充剩余部分
dw 0aa55h                     ; 魔数,必须有这两个字节BIOS才确认是MBR

  2. 编译

# nasm boot.asm -o boot.bin

      如果没有nasm,安装它 sudo apt-get install nasm, 执行完上述命令,会生成boot.bin文件,这就是我们的主引导记录二进制。

 

第四节 代码解释


   我们再来看下主引导记录的汇编代码,熟悉汇编的读者可忽略本节。

  1. 为什么MBR要从0x7c00h处开始执行?

  ORG是伪指令,org 7c00h是告诉编译器,下面代码装入到内存的起始地址0x7c00h处。为什么呢,这是因为BIOS读取主引导记录后,会从0x7c00h处开始执行,那么BIOS为什么会从0x7c00h这个地址开始执行,而不是其他地址呢,这一切都要从大明湖畔的8086cpu说起。

  时光飞逝,容颜易老,8086却还是那个样子,如图所示:

图 8086实物图

图 8086引脚图

  正如图中所示,8086cpu的地址总线宽度为20(AD0-AD19),可以传送220的地址信息,即可以定位220(1M)的内存地址空间,那么这1M的内存地址空间是如何分配的呢,见下图所示(图是386的,我们目前只关心实模式即1M内存地址空间分配):

图 实模式内存地址空间分布

  看到0x7c00h了吗?0x0000h--0x7c00h这一段存的是BIOS中断向量和一些BIOS数据等,至于到底为什么以0x7c00h为界,本文不做讨论,有兴趣看这里http://www.glamenv-septzen.net/en/view/6。

    2. int 10h是干嘛的?

当出现int 10h中断时,表示要操作显示器了,此时AH寄存器表示如何显示,代码中的AH为13h,表示要在TTY(伪终端)显示字符,此时其他几个寄存器都有一定的含义,如下所示:

ES:BP -- 显示字符串的地址    CX -- 显示字符串的长度

BH -- 页码                          BL -- 属性(若AL=00H或 01H)

DH -- 行              DL -- 列

AL -- 显示输出方式

下面一段代码也就不难理解了:

1
2
3
4
5
6
7
8
9
mov ax, cs
mov es, ax
mov ax, msg
mov bp, ax                    ; ES:BP表示显示字符串的地址
mov cx, msgLen                ; CX存字符长度
mov ax, 1301h                 ; AH=13h表示向TTY显示字符,AL=01h表示显示方式(字符串是否包含显示属性,01h表示不包含)
mov bx, 000fh                 ; BH=00h表示页号,BL=0fh表示颜色
mov dl, 0                     ; 列
int 10h

  3. $和$$是什么意思?

$   是当前位置
$$ 是段开始位置

下面两句就不难理解了:

1
2
msgLen: equ $ - msg           ; 字符串长度
times 510 - ($ - $$) db 0     ; 填充剩余部分

  4. 为什么要有0xaa55h魔数?

  BIOS检查完硬件后,会寻找下一个设备来启动计算机,BIOS找到一个设备后,会读取该设备的第一个扇区,也就是读取最前面的512个字节。如果这512个字节的最后两个字节是0x55和0xAA,表明这个设备可以用于启动;如果不是,表明设备不能用于启动,控制权于是被转交给"启动顺序"中的下一个设备。

 

第五节 制作软盘镜像,加入主引导记录  


  如何用dd命令制作软盘,自行google之。

  1. 首先,我们制作一个空的软盘镜像empty.img:  

# dd if=/dev/zero of=empty.img bs=512 count=2880

  2. 之后,我们制作一个包含主引导记录boot.bin的镜像文件lucasOS.img:

# dd if=boot.bin of=lucasOS.img bs=512 count=1

  3. 然后,将empty.img中1个扇区后的数据拷贝到lucasOS.img的后:

# dd if=empty.img of=lucasOS.img skip=1 seek=1 bs=512 count=2879

  这样就做成了一个大小为1.44Mb的包含主引导记录的软盘镜像文件lucasOS.img。

  4. 将虚拟机ubuntu中的文件lucasOS.img拷贝到windows下(鼠标直接拖拽,如果不行google之)。

 

第六节 用软盘镜像lucasOS.img启动一个空的虚拟机


 1. VMware创建空的虚拟机,去掉开机从CD/DVD启动选项。  

  2. 网络选择host-only模式。

  3. 选择从软盘驱动,路径选择上一节已经拷贝到windows下的镜像lucasOS.img.

  4. 开启虚拟机电源,看到如下画面,恭喜你,成功了。

  好了,至此,我们完成了主引导记录,后续会讨论载入内核,并进一步讨论进程管理、内存管理、文件系统和中断等等。

 

代码获取


  本系列GitHub地址 https://github.com/lucasysfeng/lucasOS.git

  获取代码:

# git clone https://github.com/lucasysfeng/lucasOS.git

  本讲的代码是code/chapter1,笔者已经将上面的命令集成到Makefile中了,读者只需进入目录,按ReadMe.txt执行即可。有问题请留言

  • 36
    点赞
  • 184
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己makefile了,会不会makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。 因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。 makefile带来的好处就是——“自动化编译”,一旦好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。 现在讲述如何makefile的文章比较少,这是我想这篇文章的原因。当然,不同产商的make各不相同,也有不同的语法,但其本质都是在“文件依赖性”上做文章,这里,我仅对GNU的make进行讲述,我的环境是RedHat Linux 8.0,make的版本是3.80。必竟,这个make是应用最为广泛的,也是用得最多的。而且其还是最遵循于IEEE 1003.2-1992 标准的(POSIX.2)。 在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。这里所默认的编译器是UNIX下的GCC和CC。
用c++/qt的项目,项目都经测试过,真实可靠,可供自己学习c++/qt。Qt是一个用标准C++编的跨平台开发类库,它对标准C++进行了扩展,引入了元对象系统、信号与槽、属性等特性,使应用程序的开发变得更高效。 Qt类库中大量的类以模块形式分类组织的,包括基本模块和扩展模块等。一个模块通常就是一个编程主题,如数据库、图表、网络等。 一、Qt核心特点 1.1.概述 Qt本身并不是一种编程语言,它本质上是一个跨平台的C++开发类库,是用标准C++编的类库,它为开发GUI应用程序和非GUI应用程序提供了各种类。 Qt对标准C++进行了扩展,引入了一些新概念和功能,例如信号和槽、对象属性等。Qt的元对象编译器(Meta-Object Compiler,MOC)是一个预处理器,在源程序被编译前先将这些Qt特性的程序转换为标准C++兼容的形式,然后再由标准C++编译器进行编译。这就是为什么在使用信号与槽机制的类里,必须添加一个Q_OBJECT宏的原因,只有添加了这个宏,moc才能对类里的信号与槽的代码进行预处理。 Qt Core模块是Qt类库的核心,所有其他模块都依赖于此模块,如果使用qmake来构建项目,Qt Core模块则是被自动加入的。 Qt为C++语言增加的特性就是在Qt Core模块里实现的,这些扩展特性由Qt的元对象系统实现,包括信号与槽机制、属性系统、动态类型转换等。 1.2.元对象系统 Qt的元对象系统(Meta-Object-System)提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统。 元对象系统由以下三个基础组成: 1.QObject类是所有使用元对象系统的类的基类; 2.在一个类的private部分声明Q_OBJECT宏,使得类可以使用元对象的特性,如动态属性、信号与槽。 3.MOC(元对象编译器)为每个QObject的子类提供必要的代码来实现元对象系统的特征。 构建项目时,MOC工具读取C++源文件,当它发现类的定义里有Q_OBJECT宏时,它就会为这个类生成另外一个包含有元对象支持代码的C++源文件,这个生成的源文件连同类的实现文件一起被编译和连接。 除了信号和槽机制外,元对象还提供如下一些功能。 1.QObject::metaObject()函数返回类关联的元对象,元对象类QMetaObject包含了访问元对象的一些接口函数,例如QMetaObject::className()函数可在运行时返回类的名称字符串。 QObject obj=new QPushButton; obj->metaObject()->className(); 2.QMetaObject::newInstance()函数创建类的一个新的实例。 3.QObject::inherits(const charclassName)函数判断一个对象实例是否是名称为className的类或QObject的子类的实例。 1.3.属性系统 1.属性定义 Qt提供一个Q_PROPERTY()宏可以定义属性,它也是属于元对象系统实现的。Qt的属性系统与C++编译器无关,可以用任何标准的C++编译器编译定义了属性的Qt C++程序。 2.属性的使用 不管是否用READ和WRITE定义了接口函数,只要知道属性名称,就可以通过QObject::property()读取属性值,并通过QObject::setProperty()设置属性值。 3.动态属性 QObject::setProperty()函数可以在运行时为类定义一个新的属性,称之为动态属性。动态属性是针对类的实例定义的。 动态属性可以使用QObject::property()查询,就如在类定义里用Q_PROPERTY宏定义的属性一样。 例如,在数据表编辑界面上,一些字段是必填字段,就可以在初始化界面时为这些字段的关联显示组件定义一个新的required属性,并设置值为“true"。 4.类的附加信息 属性系统还有一个宏Q_CLASSINFO(),可以为类的元对象定义”名称——值“信息。
什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己makefile了,会不会makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。 因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。 makefile带来的好处就是——“自动化编译”,一旦好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。 现在讲述如何makefile的文章比较少,这是我想这篇文章的原因。当然,不同产商的make各不相同,也有不同的语法,但其本质都是在“文件依赖性”上做文章,这里,我仅对GNU的make进行讲述,我的环境是RedHat Linux 8.0,make的版本是3.80。必竟,这个make是应用最为广泛的,也是用得最多的。而且其还是最遵循于IEEE 1003.2-1992 标准的(POSIX.2)。 在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。这里所默认的编译器是UNIX下的GCC和CC。
什么是 makefile?或许很多 Winodws 的程序员都不知道这个东西,因为那些 Windows 的集成开 发环境(integrated development environment,IDE)都为你做了这个工作,但我觉得要作一个好的 和专业的程序员,makefile 还是要懂。这就好像现在有这么多的 HTML 编辑器,但如果你想成为一个专 业人士,你还是要了解 HTML 的标签的含义。特别在 Unix 下的软件编译,你就不能不自己 makefile 了,会不会 makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。 因为,makefile 关系到了整个工程的编译规则。一个工程中的源文件不计其数,并且按类型、功能、 模块分别放在若干个目录中,makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需 要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile 就像一个 Shell 脚 本一样,其中也可以执行操作系统的命令。 makefile 带来的好处就是——“自动化编译”,一旦好,只需要一个 make 命令,整个工程完全 自动编译,极大的提高了软件开发的效率。make 是一个命令工具,是一个解释 makefile 中指令的命令 工具,一般来说,大多数的 IDE 都有这个命令,比如:Delphi 的 make,Visual C++ 的 nmake,Linux 下 GNU 的 make。可见,makefile 都成为了一种在工程方面的编译方法。 现在讲述如何 makefile 的文章比较少,这是我想这篇文章的原因。当然,不同产商的 make 各不相同,也有不同的语法,但其本质都是在“文件依赖性”上做文章,这里,我仅对 GNU 的 make 进 行讲述,我的环境是 RedHat Linux 8.0,make 的版本是 3.80。毕竟,这个 make 是应用最为广泛的, 也是用得最多的。而且其还是最遵循于 IEEE 1003.2-1992 标准的(POSIX.2)。 在这篇文档中,将以 C/C++ 的源码作为基础,所以必然涉及一些关于 C/C++ 的编译的知识。关于 这方面的内容,还请各位查看相关的编译器的文档。这里所默认的编译器是 UNIX 下的 GCC 和 CC。
### 回答1: ROS(机器人操作系统)是一个开源的机器人操作系统,用于为机器人提供开发、控制、计算和集成的一系列工具。它是一个开放的框架,支持各种机器人硬件,以及各种不同的软件包。它提供了一系列工具(如节点、服务、消息、发布、订阅),以帮助开发者创建和维护复杂的机器人系统。ROS的另一个优点是,它可以让开发者利用其他开发者创建的软件包,从而节省大量的时间和精力。 ### 回答2: ROS(Robotic Operating System)是一个灵活且强大的开源机器人操作系统。它提供了一系列用于构建机器人软件的工具、库和约定。 首先,ROS提供了一个分布式的框架,可以方便地将机器人的不同部分组合在一起。每个功能都可以作为一个独立的节点来实现,节点之间通过消息进行通信。这种分布式框架可以实现任务的并行执行,并提供了高度的可伸缩性。 其次,ROS内置了丰富的功能库,这些库可以加速机器人开发过程。例如,导航功能包提供了机器人导航和路径规划的库,使得开发人员可以轻松地实现自主导航功能。此外,ROS还提供了其他功能库,如感知、SLAM(Simultaneous Localization and Mapping)、机器人运动控制等。 此外,ROS注重开发者的友好性。它提供了丰富的调试和可视化工具,使开发者能够更方便地调试和监视机器人系统的运行状态。此外,ROS还拥有一个庞大的用户社区,开发者可以在这个社区中获得技术支持和分享经验。 最后,ROS是一个多平台的操作系统,可以运行在不同的操作系统上,如Linux、Windows和OS X。这使得ROS具有更好的跨平台性和通用性,可以方便地移植到不同的机器人平台上。 综上所述,ROS是一个功能强大且灵活的机器人操作系统。它提供了分布式框架、丰富的功能库、开发者友好的工具和跨平台能力。通过使用ROS,开发人员可以更高效地构建机器人应用程序,并为整个机器人行业的发展做出贡献。 ### 回答3: ROS(Robot Operating System,机器人操作系统)是一个灵活且强大的开源框架,用于构建机器人软件系统。它提供了一系列工具、库和约定,方便开发者创建、组织和管理机器人的软件。ROS最早是在2007年由斯坦福大学的机器人研究人员开发,目前已得到全球范围内众多机器人爱好者和学术界的广泛使用和支持。 ROS以模块化和分布式的方式设计,允许开发者用各种编程语言(如C++和Python)编功能模块,然后通过消息传递机制进行通信。这意味着不同的模块可以并行运行,从而实现了高度并发和灵活的开发方式。此外,ROS还提供了强大的工具,例如可视化工具和调试器,帮助开发者快速检测和调试代码。 ROS还支持跨平台的开发,可以在不同的操作系统(如Linux、Windows和Mac OS)上运行。这使得开发者能够在自己喜欢的环境中进行开发,同时还能与不同硬件平台(如传感器和执行器)无缝集成。此外,ROS还有一个庞大的用户社区,开发者可以通过ROS Wiki、邮件列表和论坛获得技术支持和交流经验。 ROS被广泛应用于多领域的机器人系统开发,包括工业机器人、服务机器人和自主无人机等。它不仅提供了底层的硬件驱动和通信机制,还提供了高级的算法和感知模块,如导航、目标识别和运动规划等。通过使用ROS,开发者可以快速构建复杂的机器人系统,提升开发效率,并且能够与其他开发者共享和复用代码。 总之,ROS是一个开源、灵活和强大的机器人操作系统,通过提供模块化和分布式的开发框架,使得机器人软件开发变得更加简单和高效。它的广泛应用和庞大的用户社区都使其成为机器人领域的首选开发平台。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值