Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1138942
  • 博文数量: 196
  • 博客积分: 4141
  • 博客等级: 中将
  • 技术积分: 2253
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-21 20:04
文章存档

2019年(31)

2016年(1)

2014年(16)

2011年(8)

2010年(25)

2009年(115)

分类: 其他UNIX

2019-02-20 16:45:05

2.1进程的概念

一个进程本质上是一个程序的执行。每个进程有其自己的地址空间,从0到一个最大值,进程可以读写该空间中的内容。地址空间中包括可执行程序、程序的数据及堆栈。与每个进程相关的还包括一组寄存器、程序计数器、指针和其他硬件寄存器,以及所有其他运行该程序所需要的信息。

为此我们考虑分时系统的工作:分时操作系统周期性地挂起一个进程然后启动运行另一个进程,例如在过去的一秒钟内,第一个进程已运行完分配给它的时间片,则要被暂停。

在上述进程被暂时挂起的情况下,之后的某个时刻它将被再次启动,而且要求再次启动时的状态与先前暂停时完全相同,这就意味着在将其挂起时该进程的所有信息都要被保存下来。例如进程以读方式打开了若干文件,每一个文件都有一个指针来指示当前的读写位置。当该进程被挂起时,这些指针均要被记录下来以保证后面的READ系统调用能够正确地执行。在许多操作系统中,除进程地址空间以外的所有信息均存放在操作系统管理的一张表中,称为进程表。进程表是一个数据结构的数组,当前系统中的每个进程都要占用其中一项。

所以一个(挂起的)进程包括两部分:进程的地址空间 - 称作核心映像(core  image),以及对应的进程表项(包含寄存器值及其他信息)。

在与进程管理有关的系统调用中最关键的是完成进程创建和进程终止的系统调用。考虑一个典型的例子。一个命令解释器(shell)进程从终端上读命令,此时,用户刚键入一条命令要求编译一个程序,为此shell必须首先创建一个进程来执行编译程序。当执行编译的进程结束时,它执行一条系统调用来终止自己。

若一个进程能够创建一个或多个进程(称为子进程),而且这些子进程又可以创建子进程,则很容易得到如图2-1所示的进程树。

图2-1进程树

2.2虚拟存储器概念

许多年以前人们第一次遇到了太大以至于内存容纳不下的程序,通常采取的解决方法是把程序分割成多个叫做覆盖块的片段,覆盖块0首先运行,在它结束时它将调用另一个覆盖块。有一些覆盖系统非常复杂,允许多个覆盖块同时在内存中。覆盖块存放在磁盘上,在需要时由操作系统动态地换入换出。

虽然覆盖块换入换出的实际操作都是由系统完成的,但是必须由程序员把程序分割成片段。把一个大程序分割成小的、模块化的片段是非常费时和枯燥的。不久就有人找到了一个把全部工作都交给计算机的办法。

这个方法被称作虚拟存储器(virtual memory)。虚拟存储器的基本思想是程序、数据、堆栈的总的大小可以超过可用物理存储器的大小,操作系统把程序当前使用的那些部分保留在存储器中,而把其他部分保存在磁盘上。例如一个16M的程序,通过仔细地选择在各个时刻将哪4M内容保留在内存中,并在需要时在内存和磁盘间交换程序的片段,那么就可以在一个4M的机器上运行。

虚拟存储器也可以工作在许多程序的片段同时存放在内存的多道程序系统中。当一个程序等待它的一部分被调入时,它是在等待I/O操作而不能运行,因此CPU可以象在任何其他多道程序系统中一样,交给另一个进程使用。

大部分虚拟存储器系统都使用了一种称为分页(paging)的技术,我们这里将讨论它。在任何一台计算机上,都存在一个程序能够产生的内存地址的集合。当程序执行这样一条指令时:

 

MOVE REG, 1000

 

它把地址为1000的内存单元的内容复制到REG中(或者反过来,这取决于计算机的型号)。地址可以通过索引、基址寄存器、段寄存器和其他方式产生。

这些由程序产生的地址被称为虚地址(virtual addresses),他们构成了一个虚地址空间(virtual address space)。在没有虚拟存储器的计算机上,虚地址被直接送到内存总线上,使具有同样地址的物理存储器字被读写;而在使用虚拟存储器的情况下,虚地址不是被直接送到内存总线上,而是送到内存管理单元(MMU),它由一个或一组芯片组成,其功能是把虚地址映射为物理地址,如图2-2所示。


图2-2  MMU的位置和功能。

图2-3是一个非常简单的的例子,它演示这个映射如何工作。在这个例子中,我们有一台可以生成16位地址的计算机,地址变化范围从0到64K,这些地址是虚地址。然而这台计算机只有32K的物理存储器,因此虽然可以编写64K的程序,他们却不能被完全调入内存运行。在磁盘上必须有一个可以大到64K的程序的完整内核映象,以保证程序片段在需要时能被调入。

图2-3  虚地址与物理内存地址之间的关系由页表给出。

 

虚地址空间被划分成称为页(pages)的单位,在物理存储器中对应的单位称为页框(page frames),页和页框总是同样大小的,在这个例子中是4K,但在现有的系统中常用的页的大小是从512字节到64K。对应于64K的虚地址空间和32K的物理存储器,他们分别包含有16个虚页和8个页框。

从理论上来讲,虚地址被分成虚页号(高位)和偏移(低位)两部分,虚页号被用做页表的索引以找到该虚页对应的页表项,从页表项中可以找到页框号(如果有的话)。随后页框号被拼接到偏移的高位端,形成送往内存的物理地址。页表的目的是把虚页映射为页框。从数学角度而言,页表是一个函数,它的参数是虚页号,结果是物理页框号。通过这个函数可以把虚地址中的虚页域替换成页框域,从而形成物理地址。

Intel x86体系结构上,页表是采用二级页表实现的。如图2-4多级页表的秘密是避免把所有的页表一直保存在内存中,特别是那些不需要的就不应该保留。比如一个需要12兆字节的进程,最低端是4兆程序正文,后面是4兆数据,顶端是4兆堆栈,在数据顶端上方和堆栈底端之间的上吉(千兆)字节的空洞根本没有使用。

让我们看看图2-4(b)的例子中二级页表是怎样工作的。在左边是顶级页表,它具有1024个表项,对应于10位的PT1域。当一个虚地址被送到MMU时,MMU首先抽出虚地址的PT1域并把它作为访问顶级页表的索引。整个4G虚地址空间(32位)已经被切成1024块,每块4兆字节,这1024个表项中每个表项都表示其中的一块。

通过索引得到的顶级页表项包含有二级页表的地址或页框号,顶级页表的表项0指向程序正文的页表、表项1指向数据的页表、表项1023指向堆栈的页表。其他的表项(用阴影表示的)未用。PT2域被用作访问选定的二级页表的索引以找到该虚页的页框号。


图2-4  (a)一个有两个页表域的32位地址、(b)二级页表

 

FOS操作系统虚拟存储器采用的是段页式存储结构。因此,在这里本文也简要介绍一下段式存储结构。

每个段由一个从0到最大的线性地址序列构成。各个段的长度可以是0到允许的最大值之间的任何一个值,不同的段的长度可以不同,而且通常也都不同。段的长度在运行期间可以改变,堆栈段的长度在数据被压入时会增长,在数据被弹出时又会减小。

因为每个段都构成了一个独立的地址空间,他们可以独立地增长或减小而不会影响其他的段。如果一个在某个段中的堆栈需要更多的空间来增长,因为在它的地址空间中没有任何其他东西阻挡,它就可以立刻得到它。段当然有可能被装满,但因为段通常很大,所以这种情况发生的可能性很小。在这种分段的或二维的存储器中指明一个地址必须提供一个段号和一个段内地址。图2-5图示了段的概念。

分段的存储器除了能简化对长度经常变动的数据结构的处理以外还有其他一些优点。如果每个过程都位于一个独立的段中并且起始地址是0,把单独编译好的过程链接起来的操作就能大大简化。当组成一个程序的所有过程都被编译和链接好以后,一个对在段n的过程的过程调用将使用由两个部分组成的地址 (n, 0) 转到地址字0(入口点)。

 

图2-5 段的概念

 

因此,在FOS操作系统中,分两步实现虚拟地址空间到物理地址空间到物理地址空间的映射。虚拟地址首先通过分段管理机制形成线性地址,再通过分页管理机制形成物理地址[1]

2.3 I/O原理

操作系统的主要功能之一是控制所有的输入/输出(Input/Output)设备,它必须向设备发布命令,捕获中断并进行错误处理,它还要提供一个设备与系统其余部分之间的简单易用的界面。

I/O设备可粗略地分为两类:块设备(block devices)和字符设备(character devices)。块设备将信息存储在可寻址的固定大小的数据块中,通常数据块大小的范围从512字节到32768字节不等。块设备的主要特征是能够独立地读写单个的数据块。磁盘是最常见的块设备。另一类是字符设备。与块结构相比,一个字符设备可以发送或接收一个字符流。字符设备无法编址,也不存在任何寻址操作。打印机、网络接口、鼠标(用作指点设备)、老鼠(用于心理学实验)以及多数与磁盘不同的设备均可被视作字符设备。

I/O设备通常包含一个机械部件和一个电子部件。为了达到设计的模块性和通用性,一般将其分开。电子部分称为设备控制器或适配器。图2-5是一个连接CPU、存储器、控制器和I/O设备的模型。

每个控制器都有一些用来与CPU通信的寄存器。在某些计算机上,这些寄存器占用内存地址空间的一部分,这种方案称作内存映像I/O。680X0系列计算机就采用该方案。其他计算机则使用I/O专用的地址,每个控制器占用其中的一部分。设备的I/O地址分配由控制器上的总线解码逻辑完成。有些生产IBM PC兼容机的厂商采用与IBM不同的I/O编址方案。除I/O端口外,许多控制器还使用中断来通知CPU它们已作好准备,使其寄存器可以读写。

 

图2-6一个连接CPU、存储器、控制器和I/O设备的模型

 

操作系统通过向控制器寄存器写命令字来执行I/O功能。例如IBM PC的软盘控制器可以接收15条命令,包括读、写、格式化重新校准等。其中许多命令带有参数,这些参数也要装入控制器的寄存器中。某设备控制器接收到一条命令后,CPU可以转向其他工作,而让该设备控制器自行完成具体的I/O操作。当命令执行完毕后,控制器发出一个中断信号,以便使操作系统重新获得CPU的控制权并检查执行结果。CPU仍旧是通过从控制器寄存器中读取若干字节信息来获得执行结果和设备的状态信息。

许多设备,尤其是块设备都支持直接存储器访问,或称DMA(direct memory access)。使用DMA时,CPU除了告诉控制器数据块的地址外,只需告诉控制器两条信息:数据块将存放在内存的地址和要传输的字节数,如图2-6所示。

控制器首先从设备中将整个数据块读入内部缓冲区并进行校验,接着它将第一个字节(或字)拷贝至DMA内存地址处,随后它对DMA地址和DMA计数分别增减刚刚传送的字节数。这个过程一直重复下去直到DMA计数变成0。此时设备控制器发出中断信号,通知操作系统数据已读取完毕,在这里操作系统无需再将数据拷贝到主存中,因为数据已经在读的过程中放在那里了。


图2-7数据块将存放在内存的地址和要传输的字节数

 

I/O软件设计的一个关键概念是设备无关性。其含义就是使程序员写出的软件无需修改便能读出软盘、硬盘以及CD-ROM等不同设备上的文件。用户可以简单地输入如下命令:

 

    sort < input  > output

就能够从各种设备上获得输入,包括软盘、硬盘、或者键盘,同时可以将输出送到各种不同的设备上,如软盘、硬盘、甚至是屏幕。不同设备之间的差异将由操作系统来处理,操作系统会调用不同的设备驱动程序来真正地将数据写到输出设备上。

I/O软件的另一个重要方面是错误处理。总的来说,错误应在尽可能接近硬件的地方处理。如果控制器发现一个读错误,它应该尽量进行处理,如果控制器处理不了,则交给设备驱动程序,可能只需重读一次就可以解决问题。许多错误是暂时性的,如磁头被灰尘阻滞导致的读错误,只需重复一次操作便可以消除。只有在低层软件处理不了的情况下才通知高层软件。在许多情况下,低层软件可以自行处理错误而不被高层软件感知。

通过将I/O软件组织成以下四个层次,操作系统可以合理、高效地实现以上目标。

l  中断处理程序(底层)

l  设备驱动程序

l  与设备无关的操作系统软件

l  用户层软件(高层)

中断是应该尽量加以屏蔽的一个概念,应该将其放在操作系统的底层进行处理,以便其余部分尽可能少地与之发生联系。当中断发生时,中断处理程序执行相应的操作,以解除相应进程的阻塞状态。

设备驱动程序中包括了所有与设备相关的代码。每个设备驱动程序只处理一种设备,或者一类紧密相关的设备。一旦决定应向控制器发送什么命令,驱动程序将向控制器的设备寄存器中写入这些命令。某些控制器一次只能处理一条命令,另一些则可以接收一串命令并自动进行处理。这些控制命令发出后有两种可能。在许多情况下,驱动程序需等待控制器完成一些操作,所以驱动程序阻塞,直到中断信号到达才解除阻塞。另一种情况是操作没有任何延迟,所以驱动程序无需阻塞。后一种情况的例子如:在有些终端上滚动屏幕只需往控制器寄存器中写入几个字节,无需任何机械操作,所以整个操作可在几微秒内完成。

设务无关软件的基本功能是执行适用于所有设备的常用I/O功能,并向用户层软件提供一个一致的接口。

尽管大部分I/O软件属于操作系统,但是有一小部分是与用户程序链接在一起的库例程,甚至是在核外运行的完整的程序。系统调用,包括I/O系统调用通常先是库例程调用。如下C语句

 

    count = write (fd, buffer, nbytes);

 

中,所调用的库函数write将与程序链接在一起,并包含在运行时的二进制程序代码中。这一类库例程显然也是I/O系统的一部分。

进程对设备、文件等获得独占性的访问权时有可能会发生死锁,为了尽可能地通用化,我们将这种需排它使用的对象称为资源。

使用一个资源的事件顺序是:

l  申请资源

l  使用资源

L  释放资源[1,10,11,12,15]

2.4文件系统原理

所有的计算机应用程序都要存储信息和检索信息。进程在运行时可以在自己的地址空间中存储一定量的信息。但其存储容量只限于虚拟地址空间的大小,对有些应用程序,这已经足够了;但对于其他的应用程序,例如飞机定票系统、银行系统或者公司记录保存系统,这个存储空间又显得太小了。

    在进程的地址空间内保存信息的第二个问题是:当进程终止时,信息随之丢失。对许多应用(例如数据库)而言,它们的信息必须保存几周、几个月、甚至一直保留。信息随着使用进程的终止而丢失是不可接受的。此外,即使系统突然崩溃,这些信息也应该设法保存下来。

第三个问题在于经常有多个进程同时存取信息(或者部分信息)。如果我们在某个进程的地址空间内存有在线电话簿,只有那个进程可以对它进行存取。解决这个问题的方法是使信息本身独立于任何进程。

由此,对于长期的信息存储,我们有以下三个基本要求:

l  必须能够存储大量的信息。

l  在使用信息的进程终止时,信息必须保存下来。

l  多个进程可以并发地存取信息。

解决所有这些问题的常用方法是把信息以一种单元,即通常所说的文件(file)的形式存储在磁盘或其他外部介质上。然后,在需要时进程可以读取这些信息或者写入新的信息。存储在文件中的信息必须是永久性的,也就是说,它不会因进程的创建和终止而受到影响。只有当用户显式地删除它时,文件才会消失。

文件是通过操作系统来管理的。文件的结构以及命名、存取、使用、保护和实现方法都是操作系统设计的主要内容。总体上,操作系统中处理文件的那部分被称为文件系统(file system)。

阅读(1454) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~