一个小型操作系统的实现
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第13章 一个小型操作系统的实现
本章知识点: 本章知识点:
13.1 MINIX概述 概述 13.2 进程 13.3 I/O任务 任务 13.4 内存管理 13.5 文件系统
为了了解到一个“真正”的操作系统是怎样 一步步构造出来的,我们将以MINIX操作系 统为例,对其设计方法进行介绍,并对其源 代码进行简单分析。 因为MINIX的源代码是公开的,有兴趣的读 者还可以自己动手加以改造。
13.2.2 具体实现
与进程通信有关的函数和过程都在文件proc.c中。 interrupt函数负责将硬件中断转换成消息,并把这 条消息发送给与该设备对应的系统任务,它将按顺 序完成以下工作:
通过判断变量k_reenter,来检查在接收当前中断时是否有 中断正在处理。若是,则将当前中断放入中断队列排队, 等待以后调用unhold操作处理; 检查目标任务是否正在等待中断,若是则发送消息,否则 就将该任务的p_int_blocked标志设置为1; 完成消息的发送:向目标任务消息缓冲区中的resourc域 和type域写入内容,并将该任务的receive标志复位,解除 该任务的阻塞,当消息复制完成后,任务就被调度执行。
13.1.1 MINIX的组成结构
shell还可以用来进行程序设计,它定义了各种 变量和参数,并提供了包括循环与分支在内的, 许多在高级语言中才具有的控制结构。 使用shell编程类似于编辑DOS中的批处理文件, 我们可以将一组我们想要执行的命令放在一个 文件中,然后像执行其他程序一样运行这个文 件。这个文件就被称为shell程序或shell命令文 件,又被称为shell script。当这个文件被运行 时,shell就会像执行输入命令那样一条条的自 动执行文件里保存的命令。
在编程的过程中,有许多常量、宏以及结构 类型的定义会经常被不同文件用到,通常把 这些定义按照某种规则或需要组织在一起, 于是就构成了头文件(header),以后缀.h 标识。1. 公共头文件 在头文件中,有一些是完全通用的,它们不 是被源文件直接引用,而是被其它的头文件 引用。 MINIX中的三个主要部分:内核、文件系统 和内存管理分别对应有三个主控头文件 src/kernel/kernel.h、src/mm/mm.h和 src/fs/fs.h。
13.2.2 具体实现
3. 进程调度 进程的调度相对来说比较简单,对照第2、3、 4层建立了三个运行进程队列。 在头文件proc.h中定义了两个数组rdy_head 和rdy_tail,它们的作用就是分别指向队列的 队首进程和队尾进程。只有就绪进程才参与 排队,而被阻塞的和取消的进程,则不会出 现在这三个运行进程队列中。
13.2.1 概述
Shell接收命令创建进程的大概框架如下所示:
13.2.1 概述
2. 进程调度 中断在操作系统中具有特殊的意义,它保证多 道程序系统能够连续工作。 MINIX的底层软件采用将中断转换为消息的方 法来隐藏中断。 每次处理中断时,都需要通过进程调度来确定 哪一个进程重新获得运行机会。MINIX中的进 程调度采用三级排队系统,分别对应第2、3、 4层。进程所处层次越低其优先级越高,2、3 层的进程可以一直运行到其自己阻塞,而第四 层的用户进程则采用时间片轮转调度。
13.3.1 I/O任务Baidu Nhomakorabea述
I/O层次及其功能: 进程利用消息实现数据读取:
13.1.2 头文件
① 在include/目录下,有三个被主控目录包 含的头文件:
ansi.h:用来测试编译器是否符合标准c的规定。 ansi.h c 整个文件的构造以#ifndef_ANSI_H为开始,并 以#endif结束; limits.h:定义了一些基本的数据值的大小,比如: 数据类型中的整形数所占位数的值等; errno.h:包含了全局变量errno返回的错误码,用 于系统调用失败时通知用户程序。
13.2.2 具体实现
系统启动和初始化流程:
13.2.2 具体实现
2. 中断处理 中断处理是由硬件和软件共同完成的,为了 避免对于烦琐硬件细节(主要是CPU的内部 工作原理)的过多涉及,我们只简单介绍硬 件完成的工作,主要侧重于软件的处理过程。
13.2.2 具体实现
硬件中断和软件中断的处理流程:
13.2.2 具体实现
4.进程通信 因为中断处理到了最后,也归结到进程间通 过消息传递信息,所以我们将从处理中断的 两个函数开始,了解MINIX中的进程间通信 过程。 在3.6.2节中曾经介绍过三种进程间利用消 息通信时所采用的同步机制,MINIX中采用 的第一种组合方法,“阻塞发送,阻塞接 收”,也就是所谓的会合原理。
13.2.2 具体实现
1. 系统启动与初始化 开机后,硬件(实际上指的ROM中的一个程序) 读取引导盘的第一个扇区,执行其中的代码, 这部分代码又引导boot程序的执行。 执行boot的目的是得到操作系统的映象。这个 映象保存在位于/minix/目录下的文件中,是由 内核、MM、FS和init被分别编译后,再将它们 链接在一起得到的。Boot本身并不是操作系统 的组成部分,在操作系统被装入后,控制权即 被转移给内核的有关代码。
13.2 进程
13.2.1 概述
计算机中的所有软件,被组织成一定的顺序 运行,这就形成了进程的概念。 在MINIX和进程有关的部分主要负责解决以 下的问题:
怎样创建和终止一个进程,并使之处于合适的队 列中(进程管理); 怎样有效调度众多进程,使之在兼顾充分利用资 源和进程特权级、优先级要求的同时保证有序运 行(进程调度),这里也包括了对中断引起的进 程状态改变的处理(中断处理); 进程之间怎样交互(进程通信)等等。
在/minix/目录中首先要注意到的是config.h文件,它被所有主 控头文件所包含,且必须列在第一位。 第三个要提到的头文件是type.h,它被主控头文件所包含,定 义了很多重要的类型及其数量值。
13.1.2 头文件
消息由如下几个部分组成:
m-source域:用于指明消息的发送进程; m-type域:用于标识出消息的类型; 数据域:包括定义为整型(int)或长型(long)的整数、字符、 字符串、字符数组、指针以及函数等。
13.2.1 概述
3. 进程通信 MINIX以消息来实现进程间的通信,并且对消息的发 送存在一些限制:每个进程(任务)可以和同层或下一 层中的进程(任务)通信,但用户进程不能直接和I/O 任务通信。 MINIX中发送和接收消息主要通过三条原语:
send(a,&message):向进程a发送一条消息; receive(b,&message):从进程b处接收一条消息; send_rec(c,&message):发送消息给进程c,并等待它的回答。 这些原语都可以通过c库函数来调用,第二个参数&message 表示的是消息数据的内存地址,消息将从发送者复制到接收 者,对于第三条原语来说,应答的消息将覆盖在原消息的地 址上。
13.1.2 头文件
② include/sys目录下主要的头文件。
由于同一种数据类型在16位和32位处理器上所 占的字长可能存在差异,因而可能因错误理解在 特定情况下使用的基本数据结构而引发问题。 在文件types.h中定义了许多MINIX使用的数据类 型及其相关的数值,从而可以避免这种情况的发 生。 通常紧跟在types.h之后的是ansi.h头文件,它们 都被所有主控头文件包含。
13.2.2 具体实现
处理软中断的工作是由sys_call完成的。和硬件中断不同,软中 断的消息来源和去向更加复杂,因此要利用proc.h中提供的两个 宏isoksrc_dest和isokprocn协同工作,检查并保证消息的源进程 和目标进程都是合法的。 检查通过后,若需要发送消息,则调用mini_send,需要接收消息 则调用mini_rec。这两个负责发/收的进程是MINIX消息传递机制 mini_rec / MINIX 的核心,Mini_send的参数主要有三个:调用的进程名、目标进 程名以及消息地址的指针。在发送之前,它还需要先进行以下的 测试: 宏isuserp测试参数caller_ptr; 检查确认目标进程不是一个空进程,否则就报错; 进行死锁测试; 上述测试通过后将进行最重要的测试:检验目标进程表项中 p_flags域中的receiving标志,以判断该进程是否在等待消息.
13.1 MINIX概述
MINIX操作系统最早出现于20世纪80年代, 由美国著名学者A.S.Tanenbaum用c语言编 制。 它从外部看来和UNIX非常相似,但实际上, MINIX的内部完全是经过重新设计的。它的 主体部分设计为几个相对独立的模块,模块 间依赖消息进行通讯,这样的模块化结构使 得对它的理解和修改都更方便。 本章中将介绍基于POSIX(国际标准9945-1) 的MINIX2.0版本,它可以运行于基于80x86 结构的兼容机系列。
13.1.1 MINIX的组成结构
Shell通常利用终端作为标准输入输出设备。但是 我们也可以利用以下的命令改变输入输出:ver <filea >fileb ,这条命令的意思是调用程序ver,从 filea文件取输入,送输出到fileb文件。 如果再利用管道,则可以将一个程序的输出作为另 一个程序的输入,例如: ver > /dev/lp,是将执 行ver程序的结果从/dev/lp文件上输出。 启动shell将首先显示系统提示符$,然后等待,假设 用户输入命令move,shell读取该命令后,自动创 建一个新进程来执行这个命令。命令执行完毕后, 它再执行一个系统调用来终止这个进程,继续等待 用户的下一个输入。
13.2.1 概述
1. 进程管理 整体来看所有用户进程构成一棵大的进程树,初始化 进程init是它们的根节点: 计算机开机以后,固化在硬件的程序从引导盘(可以是 硬盘或软盘)上将第一道第一扇区(也就是所谓的0磁道) 中的内容读入内存并从开始执行。 在系统装入完成前,所有涉及磁盘I/O的操作都要由boot 完成。 装入完成后,boot的使命就结束了。接下来就由内核启 动各项任务,然后就是MM、FS以及位于第三层的其它服 务纷纷登场。 在用户成功登录以后,可执行文件login将执行用户命令 解释器shell, shell负责接收用户命令,为每一条命令的 执行创建一个子进程。
13.1.1 MINIX的组成结构
1.MINIX的四层结构 MINIX的整个系统被分为4个层次:
13.1.1 MINIX的组成结构
需要特别介绍的是位于用户进程层次的 MINIX的命令解释器shell。 命令解释器并不是操作系统的一部分,它本 身就是一个计算机程序,用C语言编写,为 协助用户与操作系统之间通讯而设计,管理 用户与核心(kernel)之间的对话,并把操作 系统指令换成机器代码。
13.1.1 MINIX的组成结构
2. 源代码组织方式 MINIX的源代码在逻辑上一般分为两个目 录…/usr/include和…/usr/src/(为叙述方便,将简 记为include/和src/) 。
13.1.1 MINIX的组成结构
程序在内存中运行时,各个模块的分布情况:
13.1.2 头文件
13.1.2 头文件
2.专有头文件 除了公共头文件之外,在include/minix中存放的是在 任何平台上实现MINIX都需要的头文件,而 include/ibm中则存放了在IBM兼容机上实现MINIX所需 的数据结构和宏的定义。
在include/ibm目录中主要有两个文件:
diskparm.h文件由软盘系统任务使用; partition.h定义了IBM兼容机上的硬盘分区表和有关常量。
13.3 I/O任务
13.3.1 I/O任务概述 I/O系统在MINIX中是必不可少的,它 要为I/O设备配备驱动程序(实际上是 一个通信程序)以实现设备与上层之 间的通信和交互,同时负责处理由I/O 操作引起的中断。 此外,由于有些I/O设备是一种独占性 的资源,对它的使用有可能引起死锁, 这也是I/O系统要考虑的。
本章知识点: 本章知识点:
13.1 MINIX概述 概述 13.2 进程 13.3 I/O任务 任务 13.4 内存管理 13.5 文件系统
为了了解到一个“真正”的操作系统是怎样 一步步构造出来的,我们将以MINIX操作系 统为例,对其设计方法进行介绍,并对其源 代码进行简单分析。 因为MINIX的源代码是公开的,有兴趣的读 者还可以自己动手加以改造。
13.2.2 具体实现
与进程通信有关的函数和过程都在文件proc.c中。 interrupt函数负责将硬件中断转换成消息,并把这 条消息发送给与该设备对应的系统任务,它将按顺 序完成以下工作:
通过判断变量k_reenter,来检查在接收当前中断时是否有 中断正在处理。若是,则将当前中断放入中断队列排队, 等待以后调用unhold操作处理; 检查目标任务是否正在等待中断,若是则发送消息,否则 就将该任务的p_int_blocked标志设置为1; 完成消息的发送:向目标任务消息缓冲区中的resourc域 和type域写入内容,并将该任务的receive标志复位,解除 该任务的阻塞,当消息复制完成后,任务就被调度执行。
13.1.1 MINIX的组成结构
shell还可以用来进行程序设计,它定义了各种 变量和参数,并提供了包括循环与分支在内的, 许多在高级语言中才具有的控制结构。 使用shell编程类似于编辑DOS中的批处理文件, 我们可以将一组我们想要执行的命令放在一个 文件中,然后像执行其他程序一样运行这个文 件。这个文件就被称为shell程序或shell命令文 件,又被称为shell script。当这个文件被运行 时,shell就会像执行输入命令那样一条条的自 动执行文件里保存的命令。
在编程的过程中,有许多常量、宏以及结构 类型的定义会经常被不同文件用到,通常把 这些定义按照某种规则或需要组织在一起, 于是就构成了头文件(header),以后缀.h 标识。1. 公共头文件 在头文件中,有一些是完全通用的,它们不 是被源文件直接引用,而是被其它的头文件 引用。 MINIX中的三个主要部分:内核、文件系统 和内存管理分别对应有三个主控头文件 src/kernel/kernel.h、src/mm/mm.h和 src/fs/fs.h。
13.2.2 具体实现
3. 进程调度 进程的调度相对来说比较简单,对照第2、3、 4层建立了三个运行进程队列。 在头文件proc.h中定义了两个数组rdy_head 和rdy_tail,它们的作用就是分别指向队列的 队首进程和队尾进程。只有就绪进程才参与 排队,而被阻塞的和取消的进程,则不会出 现在这三个运行进程队列中。
13.2.1 概述
Shell接收命令创建进程的大概框架如下所示:
13.2.1 概述
2. 进程调度 中断在操作系统中具有特殊的意义,它保证多 道程序系统能够连续工作。 MINIX的底层软件采用将中断转换为消息的方 法来隐藏中断。 每次处理中断时,都需要通过进程调度来确定 哪一个进程重新获得运行机会。MINIX中的进 程调度采用三级排队系统,分别对应第2、3、 4层。进程所处层次越低其优先级越高,2、3 层的进程可以一直运行到其自己阻塞,而第四 层的用户进程则采用时间片轮转调度。
13.3.1 I/O任务Baidu Nhomakorabea述
I/O层次及其功能: 进程利用消息实现数据读取:
13.1.2 头文件
① 在include/目录下,有三个被主控目录包 含的头文件:
ansi.h:用来测试编译器是否符合标准c的规定。 ansi.h c 整个文件的构造以#ifndef_ANSI_H为开始,并 以#endif结束; limits.h:定义了一些基本的数据值的大小,比如: 数据类型中的整形数所占位数的值等; errno.h:包含了全局变量errno返回的错误码,用 于系统调用失败时通知用户程序。
13.2.2 具体实现
系统启动和初始化流程:
13.2.2 具体实现
2. 中断处理 中断处理是由硬件和软件共同完成的,为了 避免对于烦琐硬件细节(主要是CPU的内部 工作原理)的过多涉及,我们只简单介绍硬 件完成的工作,主要侧重于软件的处理过程。
13.2.2 具体实现
硬件中断和软件中断的处理流程:
13.2.2 具体实现
4.进程通信 因为中断处理到了最后,也归结到进程间通 过消息传递信息,所以我们将从处理中断的 两个函数开始,了解MINIX中的进程间通信 过程。 在3.6.2节中曾经介绍过三种进程间利用消 息通信时所采用的同步机制,MINIX中采用 的第一种组合方法,“阻塞发送,阻塞接 收”,也就是所谓的会合原理。
13.2.2 具体实现
1. 系统启动与初始化 开机后,硬件(实际上指的ROM中的一个程序) 读取引导盘的第一个扇区,执行其中的代码, 这部分代码又引导boot程序的执行。 执行boot的目的是得到操作系统的映象。这个 映象保存在位于/minix/目录下的文件中,是由 内核、MM、FS和init被分别编译后,再将它们 链接在一起得到的。Boot本身并不是操作系统 的组成部分,在操作系统被装入后,控制权即 被转移给内核的有关代码。
13.2 进程
13.2.1 概述
计算机中的所有软件,被组织成一定的顺序 运行,这就形成了进程的概念。 在MINIX和进程有关的部分主要负责解决以 下的问题:
怎样创建和终止一个进程,并使之处于合适的队 列中(进程管理); 怎样有效调度众多进程,使之在兼顾充分利用资 源和进程特权级、优先级要求的同时保证有序运 行(进程调度),这里也包括了对中断引起的进 程状态改变的处理(中断处理); 进程之间怎样交互(进程通信)等等。
在/minix/目录中首先要注意到的是config.h文件,它被所有主 控头文件所包含,且必须列在第一位。 第三个要提到的头文件是type.h,它被主控头文件所包含,定 义了很多重要的类型及其数量值。
13.1.2 头文件
消息由如下几个部分组成:
m-source域:用于指明消息的发送进程; m-type域:用于标识出消息的类型; 数据域:包括定义为整型(int)或长型(long)的整数、字符、 字符串、字符数组、指针以及函数等。
13.2.1 概述
3. 进程通信 MINIX以消息来实现进程间的通信,并且对消息的发 送存在一些限制:每个进程(任务)可以和同层或下一 层中的进程(任务)通信,但用户进程不能直接和I/O 任务通信。 MINIX中发送和接收消息主要通过三条原语:
send(a,&message):向进程a发送一条消息; receive(b,&message):从进程b处接收一条消息; send_rec(c,&message):发送消息给进程c,并等待它的回答。 这些原语都可以通过c库函数来调用,第二个参数&message 表示的是消息数据的内存地址,消息将从发送者复制到接收 者,对于第三条原语来说,应答的消息将覆盖在原消息的地 址上。
13.1.2 头文件
② include/sys目录下主要的头文件。
由于同一种数据类型在16位和32位处理器上所 占的字长可能存在差异,因而可能因错误理解在 特定情况下使用的基本数据结构而引发问题。 在文件types.h中定义了许多MINIX使用的数据类 型及其相关的数值,从而可以避免这种情况的发 生。 通常紧跟在types.h之后的是ansi.h头文件,它们 都被所有主控头文件包含。
13.2.2 具体实现
处理软中断的工作是由sys_call完成的。和硬件中断不同,软中 断的消息来源和去向更加复杂,因此要利用proc.h中提供的两个 宏isoksrc_dest和isokprocn协同工作,检查并保证消息的源进程 和目标进程都是合法的。 检查通过后,若需要发送消息,则调用mini_send,需要接收消息 则调用mini_rec。这两个负责发/收的进程是MINIX消息传递机制 mini_rec / MINIX 的核心,Mini_send的参数主要有三个:调用的进程名、目标进 程名以及消息地址的指针。在发送之前,它还需要先进行以下的 测试: 宏isuserp测试参数caller_ptr; 检查确认目标进程不是一个空进程,否则就报错; 进行死锁测试; 上述测试通过后将进行最重要的测试:检验目标进程表项中 p_flags域中的receiving标志,以判断该进程是否在等待消息.
13.1 MINIX概述
MINIX操作系统最早出现于20世纪80年代, 由美国著名学者A.S.Tanenbaum用c语言编 制。 它从外部看来和UNIX非常相似,但实际上, MINIX的内部完全是经过重新设计的。它的 主体部分设计为几个相对独立的模块,模块 间依赖消息进行通讯,这样的模块化结构使 得对它的理解和修改都更方便。 本章中将介绍基于POSIX(国际标准9945-1) 的MINIX2.0版本,它可以运行于基于80x86 结构的兼容机系列。
13.1.1 MINIX的组成结构
Shell通常利用终端作为标准输入输出设备。但是 我们也可以利用以下的命令改变输入输出:ver <filea >fileb ,这条命令的意思是调用程序ver,从 filea文件取输入,送输出到fileb文件。 如果再利用管道,则可以将一个程序的输出作为另 一个程序的输入,例如: ver > /dev/lp,是将执 行ver程序的结果从/dev/lp文件上输出。 启动shell将首先显示系统提示符$,然后等待,假设 用户输入命令move,shell读取该命令后,自动创 建一个新进程来执行这个命令。命令执行完毕后, 它再执行一个系统调用来终止这个进程,继续等待 用户的下一个输入。
13.2.1 概述
1. 进程管理 整体来看所有用户进程构成一棵大的进程树,初始化 进程init是它们的根节点: 计算机开机以后,固化在硬件的程序从引导盘(可以是 硬盘或软盘)上将第一道第一扇区(也就是所谓的0磁道) 中的内容读入内存并从开始执行。 在系统装入完成前,所有涉及磁盘I/O的操作都要由boot 完成。 装入完成后,boot的使命就结束了。接下来就由内核启 动各项任务,然后就是MM、FS以及位于第三层的其它服 务纷纷登场。 在用户成功登录以后,可执行文件login将执行用户命令 解释器shell, shell负责接收用户命令,为每一条命令的 执行创建一个子进程。
13.1.1 MINIX的组成结构
1.MINIX的四层结构 MINIX的整个系统被分为4个层次:
13.1.1 MINIX的组成结构
需要特别介绍的是位于用户进程层次的 MINIX的命令解释器shell。 命令解释器并不是操作系统的一部分,它本 身就是一个计算机程序,用C语言编写,为 协助用户与操作系统之间通讯而设计,管理 用户与核心(kernel)之间的对话,并把操作 系统指令换成机器代码。
13.1.1 MINIX的组成结构
2. 源代码组织方式 MINIX的源代码在逻辑上一般分为两个目 录…/usr/include和…/usr/src/(为叙述方便,将简 记为include/和src/) 。
13.1.1 MINIX的组成结构
程序在内存中运行时,各个模块的分布情况:
13.1.2 头文件
13.1.2 头文件
2.专有头文件 除了公共头文件之外,在include/minix中存放的是在 任何平台上实现MINIX都需要的头文件,而 include/ibm中则存放了在IBM兼容机上实现MINIX所需 的数据结构和宏的定义。
在include/ibm目录中主要有两个文件:
diskparm.h文件由软盘系统任务使用; partition.h定义了IBM兼容机上的硬盘分区表和有关常量。
13.3 I/O任务
13.3.1 I/O任务概述 I/O系统在MINIX中是必不可少的,它 要为I/O设备配备驱动程序(实际上是 一个通信程序)以实现设备与上层之 间的通信和交互,同时负责处理由I/O 操作引起的中断。 此外,由于有些I/O设备是一种独占性 的资源,对它的使用有可能引起死锁, 这也是I/O系统要考虑的。