操作系统概念 - Minix3

操作系统与用户程序间的接口由操作系统一组“扩展指令”定义。这些扩展指令通常称为系统调用,尽管它们可通过多种方式实现。

要了解操作系统功能,需要仔细参详这些接口。

接口中可用的调用因操作系统而异(基本概念往往相似)。

因此,只能在泛泛的概括与仔细而系统的学习间作出选择。

选择后者,要做更多的工作,但能更深入了解操作系统的真正功能。

后结章节中,将仔细研究unix(包括BSD各种版本)、linux和minix 3的基本系统调用。

简单起见,只引用minix3,大多数情况下,对应的unix和linux系统调用都基于POSIX的。

在研究实际的系统调用前,有必要鸟瞰一下minix3,大致了解操作系统是什么。

如上所述,这此概述同样适用于unix、linux。

Minix3系统调用大致分为两类:处理进程的调用、处理文件系统的调用。

进程

Minix3与其他操作系统一样,进程是一个重要概念。

进程基本上是一个正在执行的程序。

与每个进程相关联的是地址空间:一个内存位置列表,从最小值(通常为0)到最大值(进程可读写)。

地址空间包含可执行程序、数据及其堆栈。

与每进程相关联的还有一组寄存器:包括程序计数器、堆栈指针和硬件寄存器,及运行程序所需的其他信息。

后续章节中将详细地讨论进程的概念。

目前,了解进程最直观最简单方法是多道程序设计系统。

如:操作系统会定期停止运行一个进程,并开始运行另一个进程。

第一个进程在过去一秒钟中,占用CPU时间达到它所分配的份额。

当一个进程被暂时挂起后,在被重新启动时必须与停止时的状态完全相同,这意味着有关进程的所有信息,必须在挂起期间保存在某个地方。如:进程可能同时打开几个文件进行读取。

与这些文件相关联的是一个指针,它给出了当前的位置(即接下来要读取的字节或记录的数量)。

当进程被挂起时,必须保存这些指针,以便在重新启动进程后执行读取调用时,能读取到正确的数据。

很多操作系统,关于进程的信息,除进程的地址空间外,都存储在一个称为“进程表”的操作系统表中,它的结构是一个数组(或链表),每个结构对应一个存在的进程。

因此,(挂起的)进程由它的地址空间(通常称为核心映像[以纪念过去使用的磁芯存储器]),和它的处理表条目(其中包含寄存器)组成。

进程管理的关键是在系统调用时,对进程执行创建和终止。

一个常见的例子:

一个称为命令解释器或shell的进程从终端读取命令。

用户输入一个命令,要求编译一个程序。

shell现在必须创建一个运行编译器的新进程。

当该进程完成编译时,执行一个系统调用来终结自已。

Windows和其他GUI操作系统,(双击)桌面图标启动程序的方式,与在命令提示符下输入程序名称的方式非常相似。

GUI实际上是非常简单的命令解释器。

如果一个进程可创建一或多个进程(通常称为子进程),而这些进程又可以创建子进程,如下图1-5所示的进程树结构。

操作系统进程

合作完成一项工作的相关进程,通常需要彼此通信并同步它们的活动。这种通信称为进程间通信,将在后面章节详细讨论。

进程的系统调用可用于请求获取更多内存(或释放未使用的内存),等待一个子进程结束,再用另一个程序覆盖它。

有时候,需将信息传递给正在运行的进程,而不是坐在那里等它。

与不同计算机上的进程进行通信,进程需要使用网络向远程计算机上的进程发送消息。

当指定的秒数到达时,操作系统向进程发送警告信号,信号会引发进程被挂起,它的寄存器被保存在堆栈上,并开始运行一个特殊的信号处理程序,如,重传可能丢失的消息。

当信号处理程序完成时,进程在信号前的状态下重新被启动,信号是软件模拟硬件中断。

每个授权使用minix3系统的人,都被系统管理员分配一个UID(用户标识)。

启动的进程都有启动者的UID。

子进程与其父进程具有相同的UID。

用户可以是组成员,每个组都有一个GID(组标识)。

一个称为超级用户的UID(在unix中)具有特殊功能,可能违反许多保护规则。

在大型安装中,只有系统管理员知道超级用户的密码,许多普通用户(特别是学生)会花费很大的精力寻找系统的缺陷,使他们能在没密码的情况下成为超级用户。

文件系统

另一类常见的系统调用与文件系统有关。

如前所述,操作系统的一个主要功能是隐藏磁盘和其他I/O设备的特征,并向程序员提供一个干净友好独立于设备的文件抽象模型。

显然,创建文件、删除文件、读取文件、写入文件都需要系统调用。

在读取文件前,必须打开它,且在读取文件后,关闭它。

因此,操作系统提供了执行这些操作的接口。

为了提供一个保存文件的地方,minix3引入了目录的概念:作为一种对文件分组的方法。

例如:一个学生可能有一个目录,用于正在学习的每门课程(用于该课程所需的程序)。

另一个目录用于他的电子邮件,

还有一个目录用于他的万维网主页。

然后,通过系统调用创建和删除目录。

还提供了将现有文件放入目录,以及从目录中删除文件的调用。

目录条目可以是文件或其他目录。

该模型产生了如下图1-6所示的层级化文件系统。

操作系统文件系统结构

进程和文件层级结构都以树的形式组织,相似之处仅限于此。

进程层级结构通常不是很深(一般不超过三个层级)。

文件层级结构通常是4、5甚至更多。

进程层级结构通常是短暂的,一般最多几分钟。

目录层级结构可能存在很多年。

进程和文件的所有权及保护也不同。

通常,只有父进程能够控制甚至访问子进程,

但是,目录通常不仅仅只有所有者可以读取。

目录层级结构中的每个文件,都能从目录层级结构顶层根目录指定其路径,这样的绝对路径包含:必须从根目录遍历才能到达文件的目录列表,以斜杠分隔构成。

在图1-6中,CS101文件的路径是/Faculty/Prof.Brown/Courses/CS101。

前斜杠表示路径是绝对的,即从根目录开始。

顺便提一下,在windows中反斜杠(\)字符被用作分隔符,而不是斜杠(/)字符,所以,上面给出的文件路径将写成\Faculty\Prof.Brown\Courses\CS101。

后续将使用unix约定的路径。

在任意时刻,每个进程都有一个当前的工作目录,在该目录中查找的路径名不以斜杠开头。

如,在图1-6中,假如/Faculty/Prof.Brown是工作目录,那么,使用路径名Courses/CS101,将会生成与上面绝对路径名相同的文件。

进程通过发出新工作目录的系统调用改变工作目录。

Minix3中通过为每个文件和目录分配一个11位二进制保护代码,对文件和目录进行保护。

保护代码由三个3位(3-bit)字段组成:

一个用于所有者,

一个用于所有者所在分组的其他成员(用户由系统管理员进行分组),

一个用于其他所有人,

以及稍后将讨论的2位(2 bits)。

每个字段都有以下三个bit位:

一个标识读访问的位,

一个标识写访问的位,

一个标识执行访问的位。

如,保护代码:

rwxr-x-x

表示文件所有者可以读取,写入或执行该文件,

其他组成员可以读取或执行(但不写入)该文件,

其他人可以执行(但不能读取或写)文件。

对于目录(而非文件),x表示搜索权限。破折号表示缺少相应的权限(该位为零)。

在读取或写入文件前,必须打开该文件,此时将检查权限。

若允许访问,系统将返回一个称为文件描述符的小整数,以便在后续操作中使用。

若禁止访问,则返回错误代码(1)。

挂载文件系统

Minix3中另一个重要概念是挂载文件系统。

几乎所有个人计算机都有一或多个CD-ROM驱动器,可插入和移除CD-ROM。

为了提供一种处理可移动媒体(CD-ROM,DVD,软盘,Zip驱动器等)的简洁方法,Minix3允许将CD-ROM上的文件系统连接到主树。

如下图1-7(a),在挂载调用前,硬盘的根文件系统和CD-ROM上的第二个文件系统是分开且无关的。

因为,无法在根文件系统上指定路径名,所以,不能使用CD-ROM上的文件系统。

Minix3不允许路径名以驱动器名称或编号作为前缀,这是操作系统应该消除的设备依赖性。

相反,挂载调用允许CD-ROM上的文件系统连接到根文件系统。

在下图1-7(b)中,驱动器0上的文件系统被挂载在目录b上,因此,可以访问文件/b/x和/b/y。

操作系统文件挂载

若目录b最初包含文件,在挂载CD-ROM时将无法访问,因为,/b将引用驱动器0的根目录。

无法访问这些文件并不像相像的那样严重,似乎:文件系统几乎总是安装在空目录上。

如果系统包含多个硬盘,它们可以全部挂载到一个树中。

设备文件

Minix3中的另一个重要概念是设备文件(special file)。

为使I/O设备看起来像文件,提供了设备文件。

这样,就可以使用与读/写文件相同的系统调用进行读写。

两种设备文件:块设备文件(block special files)和字符设备文件(character special files)。

块设备文件通常用于由一组随机可寻址块(如磁盘)组成的设备进行建模。

通过打开块设备文件并读取,如:块4,程序可直接访问设备上的第四个块,而不考虑其上所包含的文件系统的结构。

同样,字符设备文件用于模拟打印机,调制解调器以及接受或输出字符流的设备。

按照惯例,设备文件保存在/dev目录中。 如:/dev/lp可能是行式打印机。

管道

最后一个与进程和文件相关的特性:管道。

管道是一种可连接两个进程的伪文件,如下图1-8所示。

若进程A和进程B希望使用管道进行对话,它们必须提前设置管道。

当进程A想要向进程B发送数据时,它在管道上写入数据,就好像它是一个输出文件一样。

进程B可以像读取输入文件一样从管道读取数据。

因此,minix3进程间的通信,看起来非常像普通的文件读写。

操作系统管道通信

Shell

操作系统是执行系统调用的代码。

编辑器、编译器、汇编器、链接器、命令解释器肯定不是操作系统的一部分,尽管它们很重要也很有用。

为避免混淆,在本节中,将简要介绍称为shell的minix3命令解释器。

虽然它不是操作系统的一部分,但它使用了大量的操作系统特性,因此,可作为学习使用系统调用的最佳案例。

它也是终端用户和操作系统间的主界面,除非用户使用图形界面。

目前存在许多shell,包括:csh、ksh、zsh、bash。

它们都支持以下所述的功能,这些功能来自原始shell (sh)。

用户登录时都会启动shell。

shell终端作为标准输入/输出。

首先输入提示符(如:美元符号),提示符告诉用户shell正在等待接受命令。

若用户现在输入:

date

示例中shell创建一个子进程,并以子进程运行date程序。

子进程运行时,shell等待它终止。

当子进程完成时,shell再次输入提示符并尝试读取下一行输入。

用户可将标准输出重定向到文件,如:

date >file

同理,标准输入也可以重定向,如:

sort <file1 >file2

调用排序程序,从file1获取输入,并将输出发送到file2。

一个程序的输出可以通过“管道”,作为另一个程序的输入,如:

cat file1 file2 file3 | sort >/dev/lp

调用cat程序连接三个文件,并将输出发送给sort,然后,按字母顺序排列所有行。sort的输出被重定向到文件/dev/lp,通常是打印机。

若用户在命令后放置&符号,shell不会等待它完成,只是立即给出一个提示(俗称:挂后台)。

cat file1 file2 file3 | sort >/dev/lp &

以后台作业的方式启动排序,在排序过程中用户可继续工作。