Skip to content

lutcraft/MyOrange

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

介绍

主要依据于渊老师的《Orange's一个操作系统的实现》从0实现一个初具功能的微内核操作系统.

最终实现的特性包括

  • (进入保护模式)
  • (分页)
  • (用loader启动内核)
  • (处理中断)
  • (进程和调度)
  • (命令行终端)
  • (IPC通信)
  • (扁平文件系统)
  • (内存管理)

文件系统

定义了三个结构体,分别代表超级块、i-node和 目录项。 首先必须有相应的数据结构。

  • 放Metadata;
  • 记录扇区的使用情况;
  • 来记录任一文件的信息,比如占用了哪些扇区等;
  • 存放文件的索引。

tty终端

在TTY任务中执行一个循环,这个循环将轮询每一个TTY,处理它的事件,包括从键盘缓冲区读取数据、显示字符等内容。 并非每轮询到某个TTY时,箭头所对应的全部事件都会发生,只有当某个TTY对应的控制台是当前控制台时,它才可以读取键盘缓冲区 (所以图中读取过程使用了虚线)。

和原先程序区别:

  1. 每一个TTY都应该有自己的读和写的动作。所以在keyboard_read( )内部,函数需要了解自己是被哪一个TTY调用。我们通过为函数传入一个参数来做到这一点,这个参数是指向当前TTY的指针。
  2. 为了让输入和输出分离,被keyboard_read( )调用的in_process( )不应该再直接回显字符,而应该将回显的任务交给TTY来完成,这样,我们就需要为每个TTY建立一块缓冲区,用以放置将被回显的字符。
  3. 每个TTY回显字符时操作的CONSOLE是不同的,所以每个TTY都应该有一个成员来记载其对应的CONSOLE信息。

boot启动loader,loader启动内核

512字节的引导扇区太小了,难以在其中做太多的事情,所以我们在引导扇区载入引导软盘文件系统中的LOADER.BIN,并运行之。之后再由LOADER.BIN负责将操作系统加载入内存,将CPU切换到保护模式,再跳入内核代码开始执行。

整理一下我们现在有哪些东西:

  • 一个BOOT,放置在引导扇区,从BIOS手中获取控制权,入口在7c00,负责载入LOADER,并开始运行LOADER,完全运行在实模式
  • 一个LOADER,放置在引导软盘文件系统中,将内核载入,切换到保护模式,,开启分页,最后跳入内核运行
  • 一个内核elf格式文件,放置在引导软盘文件系统中,具体内核实现 以上三者都放置在一个安装了FAT12格式文件系统的软盘中。

特权级别转换方法

调用门可以实现从低特权级向高特权级的跳转,要注意维护TSS;ret可以实现从高特权级向低特权级的跳转,要注意维护堆栈信息。

门也是AT32架构处理器在保护模式提供的一种重要机制,他的最大作用在于实现从低特权级的代码向高特权级别代码的转移。

通过call一个特权级别等于或者低于自己的门,可以跳转到门描述符中选择子指向的高特权级代码段中。

谁的特权高

一共有这么几个字段和特权级别相关:

  • CPL——在sc和ss寄存器中
  • RPL——代表选择子的特权级
  • DPL——代表段/门的特权级,在他们描述符的DPL字段中,是调用的门槛

在对数据段进行访问时:CPL和RPL都小于DPL,则可以访问。 在对代码段进行访问时:使用jmp,call,跳转到一致/非一致代码段都有差异,不能一概而论。参见书P50。

LDT与lldt

全局描述符表的确方便,我们只需要将GDT表的48位描述符赋值给gdtr,即可使用GDT表的选择子进行jmp。但实际开发中,我们往往有某些功能的段是具有紧密联系的,这些段我们可以集中放置在一张表中(LDT),将LDT表所在段的描述符维护到GDT中,再把这张表的选择子赋值给ldtr,就可以使用LDT表的选择子,直接跳转进LDT描述符描述的段中了。

备注

随着我们的程序越来越大,很快就要超过512Byte的限制了,为了解决这个问题,我们暂时先启动freedos操作系统,并且使它运行在实模式下。所以我们增加了一块freedos的软盘映像。并且将boot.asm编译成com格式,以在dos中运行。

nasm code/boot.asm -o boot.com

为了在dos环境下进行编译,我们将debug32一并拷贝进了B盘.

在进入保护模式后,我们采用Bochs段魔数停止来进行调试.方法是: 在bochsrc中添加:

magic_break: enabled=1

在boot.asm需要停止的地方加上一行代码:

	xchg bx,bx

debug32 手册

debug工具可以在dos 实模式下对com文件进行调试,调试过程中使用了DOS中断,所以到达保护跳转后会发生异常,因为此时DOS中断已经不可用.

debug 文件名.exe

-r

简单的输入-r时就是查看当前各项寄存器的值,并由当前的地址,存储的指令等等。 并且,我们可以用-r命令来对寄存器的值进行修改,如:-r ax。

-a

-a指令可以让我们依次对内存单元直接写入汇编语言,如: -a 1000:0 1000:0 mov ax,0 1000:3 mov ax,1

-d

我们可以用-d命令来查看内存中的内容,和-r类似,我们可以简单地-d来查看当前地址下往下16x8个内存单元存储的内容 同时,我们还可以通过如-d 1000:0来查看指定地址(1000:0)下的内存单元的内容,或者是用如-d 1000:0 f来查看这个地址下指定长度( f )的内容。

-u

和其它指令,类似,-u分为两种用法,-u可以查看当前地址(cs:ip)下16个内存单元所存储的汇编语言,而-u 1000:0可以查看指定地址下16个内存单元存储的汇编语言。 值得一提的是,若是此时debug打开了一个程序,则会显示该程序所包含的汇编语言(不严格按16位限制。

-p

一般是调试程序的时候用到,可以让计算机直接执行循环到结束(可类比-g)用法是遇到循环的时候直接-p。

-t

让cpu执行当前地址(cs:ip)所存储的命令,也就是单步执行.

-g

一般是调试程序的时候用到,可以让计算机执行到指定地点,如-g 0012(0012是目的ip)

-e

简单的-e 1000:00 01 02 03 04命令是可以依次从这个地址开始写入数据进内存单元(本行要一次完成,写完再摁enter之类的),或者是一个一个来,此时就是-e 1000:0之后直接摁空格,这时debug会显示当前内存的值如12.,其中12是内存单元的值,而.后的内容是你准备写入的,此时我们就写一个摁一次空格,而当我们不想输入这个单元时则可以空摁一次空格,需要退出-e时只需要摁一次enter。

-q

退出debug。

寄存器

让我们记录一下80x86系列芯片有那些常用寄存器,因为在后面的很长一段时间内,我们都将用汇编语言,离不开这些寄存器的名字。

8086

通用寄存器:

  • AX(累加器):用于算术和逻辑运算以及存储函数返回值。
  • BX(基址寄存器):通常用于存储内存地址。
  • CX(计数器):通常用于循环计数。
  • DX(数据寄存器):用于算术运算和I/O操作。

指针和索引寄存器:

  • SI(源索引):通常用于源数据传输。
  • DI(目的索引):通常用于目标数据传输。
  • SP(堆栈指针):指向栈顶。
  • BP(基址指针):通常用于指向栈底或存储堆栈帧指针。

段寄存器:

  • CS(代码段寄存器):存储当前代码段的地址。
  • DS(数据段寄存器):存储当前数据段的地址。
  • SS(堆栈段寄存器):存储当前堆栈段的地址。
  • ES(附加段寄存器):通常用于存储额外数据段的地址。

标志寄存器:

  • FLAGS(标志寄存器):包含处理器状态标志,如条件码和控制位。

80x86

通用寄存器

32位:EAX、EBX、ECX、EDX。

  • EAX(扩展累加器):用于算术和逻辑运算以及存储函数返回值。
  • EBX(扩展基址寄存器):通常用于存储内存地址。
  • ECX(扩展计数器):通常用于循环计数。
  • EDX(扩展数据寄存器):用于算术运算和I/O操作。 低16位可以当做16位寄存器来使用 去掉前缀E AX、BX... 它们的低16位可以分别当做2个8位寄存器使用 前缀变成 AH、AL、BH、BL...

指针和索引寄存器

32位:ESI、EDI、EBP、ESP

  • ESI(扩展源索引):通常用于源数据传输。
  • EDI(扩展目的索引):通常用于目标数据传输。
  • ESP(扩展堆栈指针):指向栈顶。
  • EBP(扩展基址指针):通常用于指向栈底或存储堆栈帧指针。

段寄存器

CS,DS,SS,ES 括号中为396特有

  • CS(代码段寄存器):存储当前代码段的地址。
  • DS(数据段寄存器):存储当前数据段的地址。
  • SS(堆栈段寄存器):存储当前堆栈段的地址。
  • ES(附加段寄存器):通常用于存储额外数据段的地址。

控制寄存器

CR0、CR1、CR2、CR3

  • CR0(控制寄存器0):包含控制处理器操作的标志位和系统控制位。
  • CR1-CR4(控制寄存器1-4):保留给未来使用

系统地址寄存器

GDTR 48位全局描述符表寄存器

IDTR 48位中断描述符表寄存器

LDTR 16位局部描述符表寄存器

TR 16位任务状态段寄存器

参考书籍:

英特尔IA32架构软件开发手册 第一卷

About

A toy follow 《Orange's一个操作系统的实现》

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published