自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

交换ab:a=a^b;b=a^b;a=a^b;

coding from scratch

  • 博客(97)
  • 资源 (1)
  • 收藏
  • 关注

原创 orange's学习--第十一章:使用grub多操作系统引导

将引导扇区安装到Orange'S分区的引导扇区,而不是整块硬盘的引导扇区,这样Orange'S就可以跟硬盘上其他操作系统和平共处了。做到这一点其实很容易,只需要安装一个grub就可以了。我们先将引导扇区装到Orange'S分区(硬盘的一个逻辑分区)的引导扇区:dd if=boot/hdboot.bin of=$img_file seek=`echo "obase=10;ibase=16;\...

2020-02-07 17:33:55 312

原创 orange's学习--第十一章:“安装”hdboot.bin和hdldr.bin

安装hdboot.bin也就是将它放入硬盘引导扇区中,这可以使用dd命令。安装hdldr.bin看上去不如hdboot.bin那么直接,因为它将以普通文件的身份存在于Orange'S FS。不要担心,我们可以将它打进cmd.tar这个包,然后用软盘启动一下,它就老老实实地被解压到文件系统中了。...

2020-02-06 11:17:41 263

原创 orange's学习--第十一章:如何从硬盘引导

我们先回忆一下从软盘启动的过程:1. BIOS将引导扇区读入内存 0000:7c00处;2. 跳转到 0000:7c00处开始执行引导代码;3. 引导代码从软盘中找到loader.bin,并将其读入内存(按照FAT12文件系统查找文件);4. 跳转到loader.bin开始执行;5. loader.bin从软盘中找到kernel.bin,并将其读入内存(按照FAT12文件系统查...

2020-02-06 10:46:06 238

原创 orange's学习--第十章:exec函数

exec的语义很简单,它将当前的进程映像替换成另一个。也就是说,我们可以从硬盘上读取另一个可执行的文件,用它替换掉刚刚被fork出来的子进程,于是被替换的子进程摇身一边,就成了彻头彻尾的新鲜进程了。execv( )所做的其实只是一件事,那就是向MM提供最终供调用exec的进程使用的堆栈。我们知道,main( )函数接受两个参数:argc和argv,其中的argv看上去像个细绳,实际上另一端拴...

2020-02-05 16:43:02 341

原创 orange's学习--第十章:为自己的操作系统编写应用程序

可无论Init进程fork出多少进程,它也都只是Init而已。所以我们还需要一个系统调用,它就是exec( )。exec的语义很简单,它将当前的进程映像替换成另一个。也就是说,我们可以从硬盘上读取另一个可执行的文件,用它替换掉刚刚被fork出来的子进程,于是被替换的子进程摇身一边,就成了彻头彻尾的新鲜进程了。以shell中常见的echo命令为例。我们输入“echo hello world”...

2020-02-05 16:05:33 790

原创 orange's学习--第十章:exit()和wait()

让进程死亡的系统调用叫做exit(),直译作“退出”,其实它叫“自杀”更贴切,因为exit()通常是由要进程自己调用的,而且调用之后这个进程不是“退出”了,而是干脆消失了(把进程表的进程状态设置成FREE,就不会参与进程调度了)。那么wait()是干什么的呢?如果你写过shell脚本的话,就很容易理解它的作用。我们执行一个程序之后,有时需要判断其返回值,这个返回值通常是通过$?得到。而你获取$?...

2020-02-05 10:55:50 645

原创 orange's学习--第十章:fork()函数的实现

模仿Minix中也有个INIT进程,作为用户进程的祖先。Init进程将来会fork出子进程,那么Init的所有内存范围都将被复制到新的位置,并在那里运行。如果Init用与其他进程相同的处理方法,使用0~4GB的扁平空间作为LDT描述符,那么我们在内存中将找不到另一块空间来存放它——在32位系统中,4GB是全部内存空间。那么Init进程的内存应该被限制在怎样的范围之内呢?最简单的思路就是,内核有...

2020-02-05 09:14:13 253

原创 orange's学习--第十章:fork介绍

shell的原理,说来简单,其实就是用一个子进程来执行一个命令。一个新的进程需要的要素有:自己的代码,数据和堆栈;在proc_table[ ]中占用一个位置;在GDT中占用一个位置,用以存放进程对应的LDT描述符。后两项工作比较容易完成,那第一项呢,代码、数据和堆栈从哪里来呢?传统上,生成一个新的进程时,这些都是直接从某个已有的进程那里继承或者复制。这也正解释了子进程这一概念:如果新...

2020-02-03 20:45:07 336

原创 orange's学习--第九章:将TTY纳入文件系统

原来的TTY仅仅是一个进程每隔一个时间片就把输入输出显示到屏幕上,无法把输入传递给用户进程,将TTY纳入到文件系统后,用户进程就可以获得键盘输入了。我们不妨先来想像一下TTY和文件系统连接后的情形。从用户的角度来看,读写TTY和读写普通文件将不会有差别,都是通过调用read( )和write( )来实现。普通文件和特殊文件的分辨是由文件系统来完成的,而且我们在实现文件系统时已经编写了一点...

2020-02-03 16:30:27 234

原创 orange's学习--第九章:读写文件

由于我们使用“一次分配,终身使用”的扇区分配策略,所以文件读写变得非常容易。读写普通文件时,首先是对fd_mode进行简单的判断。fd_pos的用途在于记录读写到文件的哪个位置,类似于一个书签,在文件刚打开时它被置为0。fd_inode所指向的便是被操作文件的i-node了,我们通过它获得文件的开始扇区、文件类型,以及大小等信息。需要注意,不仅读操作,写操作也需要先将目标扇区读出,...

2020-02-02 08:26:35 161

原创 orange's学习--第九章:打开文件时创建文件

打开文件函数open()要返回的是进程表filp[]内的一个索引,所以一开始我们就在filp[]内寻找一个空项,用来存放即将打开的文件的fd。由于filp[]内只保存指针,所以我们还要从f_desc_table[]中找一个空项。这两项工作做完之后,我们调用search_file( )来看看要打开的文件是否已经存在。这个函数将返回零,意思是要创建的文件肯定不存在。我们创建一个文件,需要做以下几项...

2020-02-02 07:53:27 136

原创 orange's学习--第九章:文件描述符fd

为了模仿linux的文件系统,查看一下linux下如何进行操作文件。这是一段非常简单的对文件进行创建、读写以及关闭的代码,其中用到了open( )、write( )、read( )、close( )等几个系统调用。显然,如果我们的文件系统向用户进程提供服务的话,也要实现这些系统调用,所以我们最好模仿一下它们的行为。代码所有Linux系统调用都使用到了一个变量(或者返回值),那就是fd,即“fi...

2020-02-01 20:11:04 136

原创 orange's学习--第九章:把文件系统的结构写入到磁盘

进程task_fs( ),让它调用函数init_fs( ),而init_fs( )在打开ROOT_DEV之后调用了mkfs( ),这便是建立文件系统的函数了。mkfs()就是在内存中简单的拼好数据结构,然后一下子写入一个扇区大小的内容。在mk_fs( )中,所有写入磁盘的内容都是先放进fsbuf这个缓冲区的。与通常的做法不同,我们这次没有定义一个数组,而是定义了一个指针,让它指向0...

2020-02-01 10:41:52 194

原创 orange's学习--第九章:文件系统数据结构

一个简单的文件系统大致需要这么几个要素,编写文件系统就是按照下面的图结构完成内容存储到相应的硬盘扇区位置上。定义了三个结构体,分别代表超级块、i-node和 目录项。首先必须有相应的数据结构。 要有地方存放Metadata; 要有地方记录扇区的使用情况; 要有地方来记录任一文件的信息,比如占用了哪些扇区等; 要有地方存放文件...

2020-01-31 21:03:48 227

原创 orange's学习--第九章:硬盘驱动程序

我们的硬盘驱动总共支持五种消息:DEV_OPEN、DEV_CLOSE、DEV_READ、DEV_WRITE、DEV_IOCTL。/****************************************************************************** task_hd************...

2020-01-28 20:39:45 178

原创 orange's学习--第九章:使用fdisk命令,理解分区关系

硬盘分区表其实是一个结构体数组,数组的每个成员是一个16字节的结构体。这个数组位于引导扇区的1BEh==446处,共有四个成员──因为IBM当时觉得一台PC最多会装四个操作系统。现在我们的计算机中每块硬盘经常划分成不止四个分区,这是因为每个主分区可以进一步分成多个逻辑分区。可以使用fdisk命令进行分区。...

2020-01-28 08:08:01 150

原创 orange's学习--第九章: 文件系统与硬盘分区关系

根据我们的经验,一个文件系统可以安装到硬盘的一个分区上,而且一块硬盘上可以有多个文件系统共存。你可能比我还性急,会想为什么不把文件系统直接安装到整块硬盘上呢。我得承认那样做完全可以,而且简单易行。但是我有个想法,将来何不把我们辛苦实现的操作系统装到自己的计算机上呢?到时候稍微设置一下Grub,实现多引导,让我们的操作系统跟Linux,Windows等并存。...

2020-01-27 17:29:55 226

原创 orange's学习--第九章: 文件系统理解

我们在第4章的时候就研究过FAT12。FAT12算是很简单的文件系统了,既然我们已经比较熟悉它,就让我们结合它的结构来分析一下一个文件系统都需要哪些要素。我们来参考图4.1,图分四个部分,分别是引导扇区、FAT表、根 目录区和数据区。其中引导扇区中不仅包含引导代码,而且包含BPB (见表4.1),它包含诸如根 目录文件数最大值之类的信息,可算是文件系统的Metadata;FAT表记录的是整个磁盘扇...

2020-01-27 16:59:59 298

原创 orange's学习--第九章:bximage生成一个硬盘

我们的 “机器”还没有硬盘呢,通过bochs带的命令bximage生成一个硬盘:用bximage,顷刻之间,一块80MB的硬盘就造好了。更酷的是,bximage把应该把什么放进Bochs配置文件都给列出来了,我们马上修改bochsrc,相当于把新造好的硬盘插入机器。...

2020-01-26 08:16:08 2937

原创 orange's学习--第九章:a硬盘驱动open

驱动程序的作用在于隐藏硬件细节,向上层进程提供统一的接口。由于我们的进程通过收发消息来相互通信,那么驱动程序的接口自然也是消息了。所以只要我们定义了驱动程序可以接收什么消息,也就定义了驱动程序的接口。我们先只定义一种消息:DEV_OPEN。我们过会儿通过FS任务向硬盘驱动程序发送一个DEV_OPEN消息。可是硬盘驱动程序收到这个消息之后干点什么呢?我们还是先干点简单工作:向硬盘驱动器发送一个I...

2020-01-25 15:56:37 265

原创 orange's学习--第九章:硬盘的IO端口

IPC机制将大显神通,你会发现,通过几个消息,用户进程、文件系统和驱动程序之间可以方便地协同工作。对硬盘的操作并不复杂,只需先往命令块寄存器 (Command Block Registers)写入正确的值,再通过控制块寄存器 (ControlBlock Register)发送命令就可以了。...

2020-01-25 09:33:28 210

原创 orange's学习--第八章:使用 IPC来替换系统调用get_ticks

为验证消息机制是否工作正常,我们还是从最简单的工作着手,删掉原先的系统调用get_ticks,用收发消息的方法重新实现之。不过且慢,既然是收发消息,必然是有两方参与。想想便知,我们需要一个系统进程来接收用户进程的消息,并且返回ticks值。我们就来建立一个新的系统进程,就叫它 “SYSTASK”。IPC的消息函数使用起来很简单,要从使用的角度多思考一下消息函数的实现。/**********...

2019-09-01 08:38:01 334

原创 orange's学习--第八章:实现IPC--实现msg_send()和msg_receive()

为了实现IPC的消息机制,需要为进程表增加很多成员。struct proc { struct stackframe regs; /* process registers saved in stack frame */ u16 ldt_sel; /* gdt selector giving ldt base and limit */ s...

2019-09-01 08:20:42 505

原创 orange's学习--第八章:实现IPC--实现assert ()和panic()

宏定义:#define assert(exp) if (exp) ; \ else assertion_failure(#exp, __FILE__, __BASE_FILE__, __LINE__) 这个#exp不知道什么意义注意其中的__FILE__、__BASE_FILE__和__LINE__这三个宏,它们的意义如下: 这是编译器默认展开的变量。 ...

2019-08-31 16:12:46 226

原创 orange's学习--第八章:实现IPC--增加系统调用

实现IPC--的核心乃在于 “int SYSVEC”这个软中断以及与之对应的sys_call()这个函数。其实就是增加系统调用。中断号为INT_VECTOR_SYS_CALL的系统调用函数就是sys_call init_idt_desc(INT_VECTOR_SYS_CALL, DA_386IGate, sys_call, PRIVILEGE...

2019-08-31 08:07:39 309

原创 orange's学习--第八章:IPC

IPC是Inter-Process Communication的缩写,直译为进程间通信,说白了就是进程间发消息。异步IPC,意思是说,发信者发完就去干别的了,收信者也一样,看看信箱里没信,也不坐在旁边傻等。同步IPC,它不像邮寄,倒像接力赛,发送者一直等到接收者收到消息才肯放手,接收者也一样,接不到就一直等着,不干别的。同步IPC有若干的好处,比如: 操作系统不需要...

2019-08-31 07:32:21 215

原创 orange's学习--第八章:微内核宏内核

当一个进程需要操作系统的帮助,它可以通过系统调用让内核来替它完成一些工作。你会发现,用户进程将会有很多事情依赖于内核(因为用户进程的特权级很低,很多内存访问不到,没有IO权限)。比如我们想实现一个文件系统,最起码读写硬盘的工作要求助于内核。这里我们可以逐渐地增加系统调用,但也可以采用另一种方案,就是将这些工作剥离出来,交给一些系统进程来完成,让内核只负责它必须负责的工作,比如进程调度。这种将内核工...

2019-08-25 15:35:16 179

原创 orange's学习--第七章:o实现用户printf

由于用户进程没有IO权限了,特权级低,没有权限操作显存地址,所以不能使用以前的直接输出屏幕的函数了。必须编写一个供用户进程输出使用的printf( )函数。由于printf( )要完成屏幕输出的功能,需要调用控制台模块中的相应代码,所以,它必须通过系统调用才能完成。当某个进程调用printf()时,操作系统必须知道往哪个控制台输出才行。而当系统调用发生,ring3跳入ring0时,系统只能知道...

2019-08-24 22:31:36 175

原创 orange's学习--第七章:n区分系统任务和用户进程

现在,我们有了4个进程,分别是TTY、A、B、C。其中A、B和C是可有可无的,它其实不是操作系统的一部分,而更像用户在执行的程序。而TTY则不同,它肩负着重大的职责,没有它我们连键盘都无法使用。所以,我们有必要把它们区分开来,分为两类。我们称TTY为 “任务”,而称A、B、C为 “用户进程”。在具体的实现上,也来做一些相应的改变,让用户进程运行在ring3,任务继续留在ring1。具体实现...

2019-08-24 22:14:15 101

原创 orange's学习--第七章:键盘显示器处理程序总结

键盘显示器的处理过程分成了好几个模块,重要的2个缓冲区全局变量解耦了程序。键盘扫描码缓冲区,让keyboard_handler将每次收到的扫描码放入这个缓冲区,然后建立一个新的任务专门用来解析它们并做相应处理。PUBLIC void keyboard_handler(int irq) 把键盘扫描码不加区分的存储到了键盘扫描码缓冲区,PUBLIC void keyboard_read(T...

2019-08-24 22:06:30 167

原创 orange's学习--第七章:m键盘灯处理

Cap sLock 、NumLock 、Scro llLock 键盘上这3个键有一点特殊,因为每一个都对应一个小灯 (LED)。实际上,不但通过敲击键盘可以控制这些灯的亮灭,通过写入8042的输入缓冲区也可以做到这一点。这样,我们可以维持3个全局变量,用以表示3个灯的状态,在键盘初始化的时候给它们任意赋我们想要的初值,并同时设置灯的相应状态。/*====================...

2019-08-24 21:46:53 225

原创 orange's学习--第七章:l处理退格换行

当敲击回车键和退格键时,我们往TTY缓冲区中写入 “\n”和 “\b”,然后在out_char中做相应处理。这些按键当做特殊的int值一直往下传递,传递到可以识别处理的函数再处理。对“\n”和 “\b”的处理仅仅是修改显示的显存位置的字符,修改当前字符指向的显存位置。/*==========================================================...

2019-08-18 22:38:10 892

原创 orange's学习--第七章:jk多控制台

CONSOLE这个结构中的成员按照下面初始化,original_addr和v_mem_limit用做定义控制台所占显存的总体情况,它们是静态的,一经初始化就不再改变;current_start_addr将随着屏幕卷动而变化,cursor变化更频繁,每输出一个字符就更新一次。/*========================================================...

2019-08-10 22:29:35 182

原创 orange's学习--第七章:i 多个TTY框架代码

在TTY任务中执行一个循环,这个循环将轮询每一个TTY,处理它的事件,包括从键盘缓冲区读取数据、显示字符等内容。在task_tty ( )中,通过循环来处理每一个TTY的读和写操作,读写操作全都放在了tty_do_read( )和tty_do_write( )两个函数中。当TTY任务开始运行时,所有TTY都将被初始化,并且全局变量nr_current_console会被赋值为0。然后循环...

2019-08-10 16:04:04 182

原创 orange's学习--第七章:i 多个TTY框架

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

2019-08-09 23:09:03 216

原创 orange's学习--第七章:设置光标跟随和修改显示起始地址

这么多寄存器,只有一个端口0x3D5,怎么来操作其中某一个呢?这就用到Address Register了。我们看到表7.5中每一个寄存器都对应一个索引值,当想要访问其中一个时,只需要先向Address Register写对应的索引值 (通过端口0x3D4),然后再通过端口0x3D5进行的操作就是针对索引值对应的寄存器了。如果我们把Data Registers看作一个数组,那么 Address...

2019-08-08 23:01:30 348

原创 orange's学习--第七章:显示器如何显示的

虽然在题目以及文中我们使用 “显示器”这个字眼,但它并不是一个精确的称呼,因为我们操作的对象可能是显卡,或者仅仅是显存。不过没关系,开始的不精确不代表我们不严谨,因为随着认识的深入,这些概念最终会清晰起来。目前,在模糊的地方我们可以暂时使用 “视频”这个词。 到现在才来仔细介绍视频好像有点晚,因为从一开始我们写那个简单的Boot Sector的时候,就从来没有离开过对视频的操...

2019-08-07 21:39:09 214

原创 orange's学习--第七章:g处理按键的意义单独出来

keyboard_read( )这个函数只是负责读取扫描码就可以了,至于如何处理,不应该是它的职责,因为只有更高层次的软件才能根据具体情况做出不同的反应。把处理按键的逻辑放到tty的in_process(u32 key)函数处理。不管是单键还是组合键,都使用一个32位整型数key来表示。因为可打印字符的ASCII码是8位,而我们将特殊的按键定义成了FLAG_EXT和一个单字节数的和,也不超过...

2019-08-04 15:08:28 192

原创 orange's学习--第七章:f一次按键只调用一次keyboard_read()函数

目前,一个完整的操作需要在keyboard_read()多次调用时完成。这不但让我们增加了一些全局变量,比如code_with_E0,而且让keyboard_read( )理解起来也有些困难。符合逻辑的方法是,既然按下一个键会产生一到几字节的扫描码,就最好能够在一个过程中把它们全都读出来。这其实并不困难,只需要将从kb_in中读取字符的代码单独拿出来作为一个函数,在用到的时候调用它就可以了。(这...

2019-08-04 14:59:39 618

原创 orange's学习--第七章:de 显示输入普通字符和大写字符

对扫描码的解析工作有一点烦琐,所以我们还是分步骤来完成它。不要低估了解析扫描码的复杂性,因为它不但分为Make Code和BreakCode,而且有长有短,功能也很多样,比如Home键对应的是一种功能而不是一个ASCII码,所以要区别对待。我们还是由简到繁,先挑能打印的打印一下。/*====================================================...

2019-08-03 22:19:49 166

ORANGE'S:一个操作系统的实现--电子书和源码

ORANGE'S:一个操作系统的实现--电子书以及源码,于渊著。欢迎大家一起讨论。

2018-06-16

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除