版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第第6章进程 管理示UNIX进程和管理简UNIX管本章以UNIXSystemV为主,介绍UNIX的进程和存UNIX进程和管理简系统的部分从整体上说可以分为两大部分,即“静”的文件系统和“动”的进程控制系统。文件系统主要用来存放、管理那些暂时不被处理机执行的程序和数据,它为程序和数据文件分配空间,控制文件存取和为用户检索信息。而进程控制系统则负责为将要执行的程序和数据文件分配内存空间,并负责进程调度、控制并发进程的执行速度和分配必要的资源,以及负责进程通信和内存管理等。X的进程控制系统与文件系统之间通过系统调用来互相作用。先介绍X的进程控制系统部分。系统把一个程序看作是一个可执行文件,而把一个进程看作是程序的执行或执行中的程序实例。但是,从静态的观点看,U把进程解释为由一组机器指令、数据和堆栈结构组成的集合,及其上下文。系统调度进程占据U。由于调度并不一定是在每个进程执行完毕时发生,因此,系统内同时有多个进程在执行。而且,若干个进程可以同时调用一个子程序。和其他所有操作系统一样,X操作系统只有在其内核装入内存后才能开始运行。为了使操作系统内核能在每次开机时顺利地装入内存,用户必须事先把X操作系统的执行代码以文件方式在计算机硬盘设备中,并对计算机系统中的相应资源,例如高速缓存、交换区等进行初始化。这一过程被称为操作系统的安装过程。一个的操作系统都有自己的自动安装程序。用户了操作系统之后,只要按照操作系统程序的提示和说明,一般都能进行系统安装。因此,本章的进程运行和管理都是假定在一个已完全安装完毕的操作系统基础上进行的。在一个已安装好X系统的操作系统中,启动电源意味着系统引导程序开始系统自举,引导在外存硬盘中的操作系统进入内存。这一过程是一个启动X系统、设置和初始化各种数据结构与表格、建立控制系统内核运行的控制进程(在系统中,把进程称为0#进程),和建立控制终端进程与S进程(用户交互进程)运行的1#进程。最后,系统在建立了0#进程和1#进程等之后,将出现相应的提示符,以等待用户输入命令来执行和处理用户应用程序。系统在初始过程中的运行如图6.1所示。图中,当系统创建了1#进程之后,1#进程将会调用相应的终端管理进程,为X系统的不同终端创建相应的终端管理进程和S进程,从而使每个终端上的用户都可以在S 的管理下交互使用X系统。图6.1UNIXS程序将为用户提供解释执行用户命令的交互工具。随着用户命令,例如“cp等的输入,系统将为该命令建立一个执行该命令的用户进程。如果这个用户进程抢不到处理器,则S进程会自动退出处理器,进入等待队列,以便用户进程执行。在用户进程执行结束后,S进程又恢复执行,并显示提示符和等待用户的下一条命令输入。X系统的所有进程都是在上述执行过程中产生和消亡。由图6.1可以看到,在系统中还未创建出其他新用户进程之前,只有0#进程、1#进程以及终端管理进程与S进程存在。其中,终端管理进程与S进程是1#进程的子进程,这是因为在X系统中,除了0#进程和1#进程之外,其他进程都是由父进程创建的。人们也称1#进程是所有用户进程的操作系统的0#进程在态下运行,而1#进程以及由1#进程衍生的其他进程都可在用户态和态两种执行模式下执行。在不同的执行模式下执行时,同一进程使用不同的堆栈和不同的管理数据结构。在两种不同模式下执行的程序不能互相各自的堆栈,它们之间的参数传递往往需要借助通用寄存器等硬件。两态之间的主要区别是,用户态下的进程能存取它们自己的指令与数据,但不能存取 指令和数据。然而态下的进程能存取 和用户地址。另外,某些机器的指令是 指令,在用户态下执行会引起错误,只能在 态下执行。另外,在后面的章节中将会看到, 态模式享有比用户态模式高的优先级。因此,尽管是同一进程,有时仍把它分开称为用户进程和系统进程( 进程)。的进程。它有三种功能,除了在初始化时创建1#程之外,还负责调度分配处理器以及负责进程交换。有关X进程调度和交换功能将在本章后续部分介绍。进程的态和用户态之间的转换靠中断以及硬件设置等方法完成,当用户进用户态转向核心态执行时,需要依靠中断或后述的陷阱来实现。在态执行的进程只有通过设置程序状态寄存器PS才能回到用户态。它们之间的关系如图6.2所示。图6.2UNIX进程的 口部分,进程本身的控制部分,包括进程的创建进程调度和进程的撤消等,第三部分是进程间控制部分,包括进程间的互斥、同步和通信等,第四部分是管理部分。进程控制系统模块结构如图6.3所示图6.3进程控制系进程控制系统与文件系统的接口有两个,一个是在系统与文件系统直接发生联系的有关表格和数据结构。另一个则是通过系统调用界面,也就是中断和陷阱(t&rap)总控部分与文件系统发生联系。以便把待执行的文件读入内存,或把已经执行完毕的程序和结果写入文件系统长期保存调度模块的作用是分配U。显然,在进行资源分配、特别是U分配时要按照一种既公平合理又有很高效率的分配原则。在X系统中,这个调度原则就是按照进程的优先级,每次调度具有最高优先级的进程去占有处理机。每一个进程,从它被创建的那一时刻起,就具有了一个随时间动态变化的优先级。在XstemⅤ中,系统有两个时机计算各进程的优先级。这两个时机是:每秒钟一次的时间片结束发生时钟中断时,对那些优先级大于某个常数的进程进行重新计算。当前执行进程请求系统调用后,从中断和陷阱总控程序返回当前执行的用户态时,重新计算当前执行进程的优先级。这里要的一点是,系统计算各进程优先级的时间并不总是发生进程调度的时间。UNIXSystem中引起进程调度的情况从而自己调用sleep过程,放弃处理机进入睡眠状态。为了与其他并发进程保持同步,调用了t或stop过程等,从而主动放弃了处理机而进入睡眠状态。当系统发现系统中某进程的优先级已高于当前执行进程的优先级时,系统设置一个名叫runrun的调度标志。但是,系统并不在runrun标志刚被设置时就开始调度。它要等待到系统在态下的程序执行完毕,由态转入用户态时,也就是在中断陷入总控处理程序结束之前的瞬间,检查runrun标志并进行调度。时间片用完,且当前进程的优先级低于其他就绪进程。当前进程调用exit,自我终止时进程通信是XtemⅤ的一个重要组成部分。进程通信既包括用来控制各并发进程执行速度和资源共享与竞争的低级通信,也包括进程之间大量传递信息的高级通信。系统在态下执行时,系统进程只能借助p原语和p(或t-run)原语实现同步。p原语使当前执行进程以指定原因和优先数睡眠,而p则唤醒在指定原因上睡眠的所有进程。用户进程不能使用p原语和e-up原语。用户进程之间要实现同步通信的话,一种办法是利用系统提供的软中断信号进行通信。mⅤ为用户使用软中断通信提供了相应的系统调用。另一种办法是调用系统调用t或p使得当前执行进程进入等待状态,直到所等待事件发生时由唤醒或睡眠到一定时间后自动唤醒。用户进程之间实现同步的高级办法是使用temⅤ提供的信号量方法。temⅤ中的模块为进程间的大量信息传送提供了众多的系统调用。除了上述通信之外,X还提供了一种称之为管道(e)的信息传送。它以临时文件的方式,实现同一主机内的进程之间批量数据的单向、先进先出方式的无格式字符流传送。管理模块控制分配。任何一个待执行进程,如果它不能在内存中占据必需的容量,它是不能执行的。换句话说,U绝对不会执行一个全部内容都在外存的进程。然而,内存是一种有限而又昂贵的资源,它不可能容纳系统中全部活动进程。存储管理系统必须决定把哪一个进程的哪一部分留在内存中,而把哪一部分放在外存。也就是说,管理部分管理进程在内存和外存之间的信息转移,以便所有进程都得到公平执行的机会。下面先介绍UNIX系统的进程结构UNIX本节将进一步介绍UNIXSystem进程的静态构成进程的概在X系统中,进程被赋予了下述特定的含义和特性:一个进程的存在意味着在所谓的“proc”数(PCB的常驻内存部分)中有一个非零的结构存对于每一个进程有一个被称为U区或r结构的数据结构。这个数据结构放置该进程的私用控制信息,且在进程被创建时才会由系统分配相应的域。一个进程可一个进程是获得和释放各种系统资源的基本单位。上述第(1)点是反映进程动态特性的,而第(2)点与第(3)点又反映了进程的静态特性。第(4)点与第(5)反映了系统的进程之间的关系以及X没有作业概念的特性。事实上,由第3章可知,一个进程的静态描述是由三部分组成的,即进程状态控制块(栈段),进程的程序文本(正文)段以及进程的数据段。在第3章中,把这三部分统称为进程上下文,而进程的动态特性则定义为在进程上下文中的执行。首先介绍UNIXSystem进程的虚拟由于XtemⅤ进程的虚拟地址结构是依赖于硬件,因此,如果不作特别说明,本文默认那些与硬件有关的部分都是依赖于1的。进程的虚拟地址结如上所述,UNIXSystemⅤ的进三个逻辑段组成:即存放状态控制块的栈段、存放CPU执行指UNIXSystemⅤ中,一个进程的虚拟地址空间被分成若干个逻辑区(logicalregion)来存放上述三个逻辑段。区是进程虚拟地址空间上的一段连续区域,它是被共享、保护以及进行内存分配和地址变换的独立实体。正文、数据和栈分别存放于各自的区中。这里,要强调的一点是进程的虚拟地址在各区之内是连续的。为了管理每个进程中的区,系统设有一个称为区表的数据结构,每个在系统中存在的区都在该表中占有一个表项。区表包括下列内容:区的类型,指明该区存放正文段、数据段或私有数据及栈段。区的长度区的状态,包括是否已被调入内存,是否正在调入内存过程中,是否被锁住,以及是否正在被请求调入内存等。文件系统指针,指向外存中与该区对应的数据文件。区表如图6.4所示图6.4系统区在系统创建新进程时,将从区表中分配相应的表项给所创建的进程。为了把区表和进程联系起来,当进程中的某个逻辑段在区表中分得表项并填写了相关栏目之后,将把该表项的内存地址返回到进程的oc结构中。oc结构中与区表项有关的还有该段在虚存空间的起始地址,内存中的页表地址及页表长度等。关于oc结构,将在后面讲述。把区表和进程oc结构分开的原因之一是便于共享,因为每个逻辑区(段)在不同的进程中对应的虚拟地址是不同的,但它们却可以通过区表而对应变换到同一物理内存空间。区表和进程oc结构的关系如图6.5所示。图6.5区表与进程proc结在系统创建一个进程或让一个进程共享其他进程的某个段时,在分配区表项后或在改变有关区表项共享计数位后,把这些区表项与有关进程连接起来。对新进程的连接是在创建oc结构时填写区表项地址,该区表项对应逻辑段的虚拟地址、所需页表的内存始址、逻辑段长度等。对共享段的连接只要填写区表项地址、页表内存始址和长度即可。但是,共享段的虚拟地址在不同的进程中是不一样的。SystemⅤ中的区和段页式管理中的段非常相像。的,而UNIXSystemⅤ的各个进程的分区虚拟地址仍是一维的。另外,UNIXSystemⅤ的分区并不是 进程上下UNIXSystem的进程上下文是由正文段,也就是CPU执行指令的集合、数据结构、和有关寄进程上下文的各个部分按照一定的规则分布在进程虚拟空间的不同位置上。对于不同的机器和硬件结构,进程上下文的分布规则不同。例如,在X-1型机上,其虚拟地址空间划分为进程空间和系统空间两大部分。其寻址范围为232个单元,即4096M位。其中,虚拟空间的低位地址的半部分(0~231-1)是进程虚拟空间,其余为所有进程共享的系统空间,操作系统程序占据这个区。代码。这个段的起始虚址为0,且可以动态地向高保护的进程代码和数据,P1区从231-1单元开在图6.6中,态栈(kernalstack)是该进程执行程序时,保留的栈副本。该栈中装有进调用函数时用到的有关参数等,另外,还包系统调用的调用序列。设置栈的目的是使进程在执行了不同调用顺序的函数之后,仍能返回到原来的用户态下执行。栈具有多个层次,其中每层可保留一次调用或中断处理后,返回被中断程序处继续执行所必需的有关寄存器的值。图6.6进程空间结由main(argc,argv)过程调copy(old,new),过程copy(old,new)更进一步调用库函write来调用write的结构。系统调用使用专门的陷阱指令然后,用户态执行转变为程序执行,并使用由于内核保护的原因,用户栈和栈之间不能互相传递参数。因此,如果要把用户程序中的参数传递给函数,必须通过通用寄存器和进程的PCB结构。图6.7执行copy程序时用户栈和栈的变进程空间的用户进程正文段、数据段、用户栈、核心栈以及有关的代码和数据是以进程为单位独立的。它们根据需要换进换出内存。在系统虚拟空间部分存放的进程上下文部分是:系统程序用页表、进程页表、oc结构、正文段和数据段等。系统虚拟空间的内容常驻内存,不因内存的大小或执行情况而换进换出。另外,由于核心正文段和与它们有关的数据结构、系统页表是被所有进程共享的,在X系统中,不把它们看作进程上下文的一部分。进程上下文进程上下文由oc结构、r结构、用户栈和栈的内容、用户地址空间的正文段、数据段、硬件寄存器的内容以及区表和页表等组成。proc结的oc结构和r结构相当于在第3章中介绍的进程控制块B。之所以把进程控制块分成两部分的原因是r结构中主要包含那些只有进程执行时才被使用的控制信息,从而,这些信息可以不必常驻内存而节省内存空间。UNIXSystem的proc结构主要包括以下各标识进程的状态用的状态位。UNIXSystem共有9个状态编码。若干用户标识号,简称D或用户I。这些用户标识号该进程属于哪一组用户,具有何种,例如是否可以互相发送软中断等等。若干进程标识号,简称PID或进程ID,说明进程区位置和长度,指明进程在内存或在外存中的位置及大小。这些信息在进程换入换出,以及状态转换等时用到。调度参数,包括优先数等。用它们决定进程转换到态和用户态的次序以及占有处理机的次序。软中断信号项,记录发向一个进程的所有未处理的软中断信号。各种计时项,给出进程执行时间和系统资源的利用情况。这些信息用来为进程计账、计算调度优先权,以及发送计时信号等。user结构的起始地址项进程页表指针,用于CPU内存时的地址变换user结user结构则主要包括以下各指向proc结构的指针,标识出对应于该user结构proc结构一个含有系统调用结果的返回值项,当系统调用执行结束之后,所得结果存放该项中以便用户程序可以使用。与用户标识有关的若干项,它们决定进程的各种权限,如存取权限等。与文件结构有关的若干项,它们描述文件的当前和当前根,以及进程的文件系统环境。用户文件描述符表,记录该进程已打开的文件中断及软中断处理的有关参数,依靠这些参数出错管理项,记录系统调用过程中遇到的错误,以便系统或进程做相应的处理。与上下文切换、现场保护有关的各项,它们保存通用寄存器的用户区地址,保存各种寄存器的当前值,进程的栈和用户栈指针,程序计数器和处理机状态字等当前值。各种计时项,记录进程及其后代在用户态和态下执行时各自所用的时间。进程数据段由以上oc结构与r结构的组成可知,oc结构中存放的是系统感知进程存在所必需的数据和信息,而r结构中存放的是进程执行时所必需的各种控制数据和信息。因此,系统在内存中开辟有的oc结构区域,使oc结构常驻内存且系统可存取任一oc结构。而r结构则不常驻内存,且只有当一个进程被创建成功时,系统才为其分配r结构空间。r结构的各项只能由其执行中的进程自己存取。关于用户栈和栈已在上一小节中作了说明,这里不再重复。寄存器内进程上下文所包含的寄存器内程序计数器PC的内容,CPU将要执行的下PSW,PSW给出机器与该进程相关联的硬件状态PSW包含当前执行进程的方式,即是在态下还是在用户态下执行。另外,还包含中断优先级,以及中断或陷入之前的方式等。栈指针,指向栈中下一项的当前地址。至于指针是指向栈还是用户栈,则由U执行方式确定。通用寄存器,用来存放进程在执行期间所产生的中间结果或参数。例如,通用寄存器0和1就是在用户进程与系统进程之间传递参数和返回值时用的。区表和页了进程各部分从虚拟地址到物理地址的。如果存在多个进程共享某个公用区(正文区或数据区那么这个公用区将是每个进程上下文的一部分(注意,这对系统程序是不成立的)。进程正文段、数据拟地址空间(0~231-1)部分,由区表和页表等组址。由于UNIXSystem采用交换操作和请求页式虚存,因此,进程虚拟地址空间的许多部分不总驻留在内存中,但它们仍是进程上下文的一部分。这一点与的早期版本有区别。一个进程的生命期是由一组状态来刻画的。这些状态是进程oc结构的一部分。UNIXSystem中进程共有9个状态,它们是进程在用户态下的执行态SRUN进程在态下的执行态SRUN进程是在用户态下还是在态下执行主要由处理机状态字PSW来区别。进程处于就绪态SRUN,只要程序调度到它,进程处于就绪态UN,但交换程序已将其换出内存。只有等待交换程序把它换入内存之后,才能调度它去执行。进程正在睡眠,且驻留在内存中的状态SSLEEP进程正在睡眠,但交换程序已将其换出内存的状态。进程正从态返回用户态。但抢先于它作了进程上下文切换,以调度别的进程执行。最后,当该进程再次被调度到时返回用户态。进程刚被创建时,由于正在进行资源分配,因此,既不是就绪态,也不是睡眠态。这个状态可被认为是进程的初始状态。图6.8给出了UNIXSystem的进程状态转换图。图6.8进程状态转换图6.8反映了一个进程从被创建到被释放的整个生命周期内的变化过程。状态之间的转换有些是通过系统原语或函数完成(例如唤醒或调度等)。有些则由外部事件的发生而导致状态转换(例如陷阱或中断)。首先,当父进程执行系统调用fork时,被创建进程进入图中状态8,即创建状态。在该状态时,为该进程分配结构区以及必要的内存工作集。内存管理分配程序如果能为该进程分配足够的内存,则进程状态发生变化,由状态8进入内存就绪状态3。此时,由于该进程已分得存放r结构,各种页表、堆栈、部分正文段和数据段所用的内存空间,因此,该进程可以经调度选中后占有U。状态8进入外存就绪状态5。如果进程处于状态5,则只有在交换程序将进程上下文换入内存成为状态3之后,才有可能被调度执行。当进程进入状态3后,进程调度程序将会在适当时机选择该进程去执行。这时,该进程在态下执行,以装配该进程的进程上下文。在这个状态下,该进程完成有关fork部分的工作。当该进程完成fork系统调用后,它可能返回用户态下执行用户程序,这时进入状态1。据UNIXSystem的调度时机规定,此时若有优先高的进程去占据处理机,从而进入状态7。进程进入状态7之后,所处的地位与状态3相同,即当进程处于状态1时,用户程序中由于使用系统调用或由于输入输出数据等而发生陷阱与中断。这样,进程又进入状态2而变为在态执行。进程在态执行时,因为等待某事件发生,例如等待输入输出完成时,调用p原语进入睡眠状态。处于睡眠状态的进程因为内存的限制,将在睡眠一段时间后被交换程序换出内存而进入外存睡眠状态6,直到事件发生后被唤醒原语唤醒而进入状态5。在进程完成它所要求任务之后,将使用系统调用exit,从而使得进程进入僵死状态9而释放资源。小在本节中,讨论了XtemⅤ中进程的虚拟地址空间,并介绍了进程的上下文和进程的状态及转换。进程的虚拟地址空间是进程管理和内存管理的基础,XtemⅤ采用了分区连续虚拟地址空间的方法。这使得进程之间程序或数据段的共享更加容易。进程上下文是进程的静态描述。oc是系统感知进程存在的唯一实体。oc结构中的各项是系统调度、控制进程必需的,因此,必须常驻内存。反过来,结构是进程执行时才要用到的控制信息,因此,如果一个进程不在执行过程中,其r结构是不必调入内存且不能被系统或其他进程所的。进程上下文中的正文段和数据段是进程完成所要求任务的关键部分,通用寄存器、程序计数器以及处理机状态寄存器和页表、区表等都是为了正文段的顺利执行而用来存放中间结果、传递参数,或存放下条指令的虚拟地址,或区别控制U的模式和完成地址变换等功能的。进程上下文各部分构成十分巧妙, 。另程可以在用户级对某些状态的转换加以控制。例如,用户可以创建进程,可以利用系统调用从用户态进入系统态。但是,有些状态转换是由系统控制的。例如,被创建进程是转换到内存就绪态还是外存就绪态取决于内存管理程序。有些状态转换则要依靠外部事件和系统的共同控制。例如,一个处于睡眠态的进程何时能转换成就绪态则依赖于事件的发生和唤醒原语。总之,进程的上下文和状态转换刻画了X进程的静、动两种特性,它们是进程的完整反映。UNIX件系统的第0块),并将其装入内存,在装入内存后,系统开始执行启动过程start。启动过程start首先初始化系统数据结构。例如,构造空闲缓冲区、初始化区结构、页表项等。然后,系统将根文件系统安装到根“/”下,并建立系统调度进程的oc结构oc[0],并使根“/”成为进程0的当前 。在创建和设置好进程0的环境之后,系统就作为进程0执行并调用fork过程创建新进程1(这里的fork不是系统调用),也就是设置proc[1]的有关表项。进程1在系统中被称为init进程。它是一个既可在由调用系统调用exec执行程序“/etc/init”的代码组成,进程1负责初始化所有新的用户进程。进程1调用exec执行“/etc/init”程序后,为每个终端生成一个子进程,然后等待用户在终端 用户在终端上输入命令,每个命令都对应于一个可执行文件。s命令解释程序解释此命令,找到相应的可执行命令文件,用系统调用fork()创建子进程,并由此子进程调用系统调用exec()执行此命令文件;父进程也就是终端进程则处于等待状态,子进程执行文件结束后调用系统调用exit()自我终止。唤醒父进程做善后处理并转而显示提示符,准备接受下一条命令执行。进程启动及进程树的形成过程如图6.9图6.9进程树的形进程控进程的创该节主要讨论用户进程的创建、执行和自我终止问题,与此相对应,X系统提供有相应的系统调用fork(),exec()和exit(),以便在用户级上实现上述功能。fork的功能是创建一个子进程。调用fork的进程称为父进程。系统调用fork的语法格式是:pid=forkpid与proc结构中某些特性参数不同之外,其他完全相同。CPU在父进程中时,pid值为所创建子进程的进程号,若在子进程中时,pid的值为零。为了便于理解X系统进程的并发性,下面介绍一下fork的功能与实现过程。系统调用fork通过执行程序fork过程完成的功能是:为子进程在proc结构表中分配一个空项为子进程赋一个唯一的进程标识号pid一个父进程上下文的逻辑副本。这里的逻辑副本是指不把父进程中那些可被共享的部分到新 增加与父进程相关联的有关文件系统的进程计数。对父进程返回子进程的进程标识号,对子进程返回零。换空间存放子进程的上下文。在资源满足的条件下系统在proc结构中为子进程分配一空表项系统在分配给用户oc结构表时,对用户同时拥有的进程个数有一定的限制,以免妨碍其他用户创建进程。另外,普通用户不能占用oc结构表中的最后一个表项,以防系统发生死锁而无法正常退出。再者,系统为新创建进程所分配的标识号按比最近一次分配的进程标识号大1的顺序递增。当标识号达到所规定的最大值之后,则从0开始重新循环。图6.10fork流程紧接着,系统从父进程oc结构中,把除了pid等之外的大部分项到子进程oc结构中。然后,系统设置子进程的各种调度参数,并把子进程状态置为I(创建态)。然后,系统调整进程与文件的接口,使得子进程自动共享父进程所打开的文件,以及确定子进程在文件系统中所处的 位置(有关文件系统,将在面的章节中讲述)。下一步,系统将把进程的上下文中的寄存器内容存在父进程的fork保存区(fork的栈)中系统在保存的寄存器内容中,包括程序计数器和处理机状态字等内容。这些内容将在后述各步中给子进程,以便子进程执行时能识别出自己是子进程,并从这里开始执行。接着,系统开始把父进程的上下文到子进程中去。这包括为子进程的r结构区及页表等分配内存和进行。另外,如果父进程的正文段和数据段不允许共享的话,则也要将这些非共享部分到子进程的内存区或外存区中。对于那些允许共享的部分,则只要增加相应的共享计数值就行。子进程的r结构除了指向oc结构表项的指针与父进程的不同之外,其他部分与父进程的结构完全相同。以上的上下文部分是进程的静态部分,除了复制父进程的静态上下文之外,系统也将保存有寄存器内容的栈内容到子进程的栈上去。以利于进程能从系处开始执行。注意在有的计算机中,栈是作为r结构的一部分实现的,因此不必再另外需要内存和进行专门的。但有些计算机中, 栈不是r结构的一部分,此时,则需把 栈 到子进程的一个私有 区上。由于子进程的上下文需要足够大的内存,有时内存空闲区是不能满足这个要求的。这时,上述复制只好在虚空间完成,也就是说,所创建的子进程上下文将被换出内存空间。否则,父进程将子进程的状态改为“内存就绪”之后,从态准备返回到用户态。如果此时不发生进程调度和不调度到子进程执行,则父进程将子进程的d返回给用户后回到用户态执行。否则,调度算法调度到子进程执行,子进程返回零值给用户后,完成fork调用返回用户态执行。执行一个文件的调当父进程使用fork创建了子进程之后,子进程继承了父进程的正文段和数据段,从而限制了子进程可以执行的程序规模。那么,子进程用什么办法来执行那些不属于父进程正文段和数据段的呢?这就是利用系统调用exec()或exece()。系统调用exe引出另一个程序,它用一个可执行文件的副本覆盖调用进程的正文段和数据段,并以调用进程提供的参数转去执行这个新的正文段程序。系统调用exec()包含六种不同的调用格式,但它们都完成同一工作,即把文件系统中的可执行文件调入并覆盖调用进程的正文段和数据段之后执行。有关ex的各种系统调用的区别主要在参数处理方法上。这些系统调用使用不同的输入参数、环境变量和路径变量。execvp(filename,argp)execlp(filename,arg0,arg1,...,(char其中,filename是要执行的文件名指针,argp参数序列的指针,而0则是参数序列的结束标志。例:用execlp调用实现一个的基本处理过程。利用fork-exec可实现一个s的基本功能。用户输入命令后,按以下步骤执行用户命令(图6.11)。利用fork利用exec,启动命令程序利用wait图6.11 执行过用C语言实现的程序例如下#include〈stdio.hmain({charcommand[32];char*prompt=“$”;while(printf(“%s”,prompt),gets(command)!={if(fork()==execlp(command,command,(char*)0)}}
wait(0) 进程的终系统调用exit(rv)自我终止当前进程SZOMB僵死状态,等待父进程进行善exit调用将导致释放除oc结构之外的所有资源,并清除进程上下文。父进程在收到子进程的信息v和有关子进程的时间信息之后,将释放子进程的oc结构和将有关时间信息加到自己的oc结构的有关项中去。UNIXUNIX系统的调度与交换都是进程0的两个部分。们分别swtch过程和sched过程实现。事实上,用于交换的sched过程是把处于外存就绪态的进程系统中没有高级调度)。因此,有时也把进程0称进程调调度原UNIX系统的进程调度采用多级反馈轮转调度(RoundRobinwithMultipleFeedback)即系统给进程分一个时间片,当时间片结束时,动态计算该进程的优先级,若有优先级高于当前进程的内存就绪态进程时,系统设置调度标识,在由核心态转换到用户态前由h过程调度优先级高的进程执行,并把被抢先的进程反馈到相应的优先级队列中。一个进程在它结束之前,可能要经过多次反馈循环。的进程调度按时间片计算优先级,并按优先级的高低来调度进程,抢占处理机。因此,X系统的进程调度是基于时间片加优先级的。UNIX的进程调度涉及的主要问题是调度的时机调度标志设置调度的实现下面,分别说明这几调度的时在系统中,为了减少操作系统设计的复杂性和提高系统执行效率,对操作系统程序采用了伪异步执行方式。也就是说,设计认为在系统程序执行期间不会发生调度或发生调度的时间是可预知的。然而,由于调度程序h又是进程0的一部分,也就是说是系统程序,这又要求调度必须在态下完成。怎样把这二者统一起来呢?显然,采用系统调用的方式向用户开放进程调度是不可取的,这一是导致系统无法控制,二是可能造成系统瘫痪和很多意想不到的问题出现。X的设计者们采用了当处理机在执行完程序之后向用户态转换之前的瞬间,检查各就绪进程的优先级进行调度的方法。由用户态转而执行程序的可能性很多。例如中断处理和陷阱处理,系统调用等。另一种可以切换处理机的时机是:当进程因申请系统资源而未得到满足,从而调用过程p放弃处理机;或者是进程为了与其他进程保持同步而调用t或stop程序放弃了处理机;或由于执行了exit调用,终止了当前进程。这几种情况下,由于发生调度的时机是可以预见的,因此,在这些程序执行结束之前,都自动调用h过程调度其他优先级高的进程执行。综上所述,XtemⅤ中,发生进程调度的时机实质上只有两个:一个是进程自动放弃处理机时自动转入调度进程,另一个则是在由态转入用户态时,系统设置了高优先级就绪进程的强迫调度标识。调度标识的设UNIXSystem中有三个关于调度和交换用的调度runrun标识是要求处理机调度程序进行调度的标识,由唤醒原语p、n及优先级设置过程i在发现某进程的优先级高于当前进程的优先级时,设置runrun标识。另外,每隔一秒一次的时钟中断处理中也将检查各就绪态进程的优先级而设置runrun标识。只要设置了该标识,在中断陷阱程序结束之前,系统就会调用h过程调度具有最高优先级的进程执行。runin和runout标识是用于就绪进程换入换出内存的。runin表示内存无足够空间换入一个外存就绪态进程,设置runin标识也意味着内存中无适当的进程可以换出。runout标识与runin相反,它表示外存XtemⅤ采用动态优先数调度策略。在系统中,优先数越大优先级越低。调度策略从内存就绪队列中选取优先数最小的进程投入执行。SystemⅤ采用下式计算各进程的P-pri=P-CPU/2+PUSER+P-nice+其中,PUSER和O是称为基本用户优先数的阈值。在temⅤ中,这两个数是常数,分别为25和20。-U为每个进程的最近一次U使用时间。当进程使用U时,系统每个时钟周期对该进程的P-U加1,最多时该值可达80。另外,系统按每秒钟的时间间隔对-U执行除以2的衰减操作。这样,如果系统的时钟周期为16.667ms的话,则系统进行每秒时钟中断处理时,-U的值将由60变为30。-e是系统允许用户设置的一个进程优先数偏移值。temⅤ中,-e可以被设置成0~40间的一个数。但一旦设置之后,除了超级用户可以将其减小之外,普通用户仅能作增加的改变。显然,由于新创建的进程未使用CPU,其P-CPU值为0,因而具有较高的优先级。但随着被调度执行,其P-CPU的值将会不断增加,从而在每秒1次的时钟中断处理时,将被其他P-CPU值小的进程所抢先。然后,随着其他进程的执行以及每秒1次的CPU值的衰减,当其优先数小于当前进程和其他调度的实进程调度是由swtch过程实现的。这里swtch的执行过程swtch过程实质上是完成一个进程之间的上下文切换第一阶段检查决定是否做上下文切换和系统是否允许做上下文切换。如果允许做上下文切换的话,则保存当前进程的上下文。在XSystemⅤ中,系统通过任意的上下文切换来保证数据结构的完整性和一致性。在做上下文切换之前,系统必须保证各种正在更新的内部数据结构都已完成,各种队列都已正确,各种数据结构的加锁、 都已完成等。在保存了当前进程的上下文之后,紧接着swtch过程要先恢复进程0的进程上下文,以提高优先级和为在UNIXSystem中,当前进程上下文的保存工作主当前进程的有关寄存器内容及栈指针的保存是由过程(u-rsav)完成的。该过程把有关寄存器内容保存在 栈中或r结构中的u-rsav和u-b中 第二阶段属于进程0部分。第二阶段使用本节前面所述的调度算法,从内存就绪队列中寻找一优先级最高进程。若内存就绪队列中没有这样的进程存在,则调出idl过程循环等待某进程变为就绪状态。若就绪队列中有符合条件的进程存在,则选取该进程占据处理机。第三阶段属于被选中进程。该进程已成为当前进程,因此,它调用esum,从它的栈或r结构中的u.u-rsav及u.u-b等中恢复该进程的有关寄存器内容和栈指针,从而使得新进程开始正常执行。交的早期版本BSD4.0以前)在内存和外存之间传送整个进程,从而给交换赋予了特殊的含义。即将内存中的整个进程上下文换出内存后将驻留在外存的整个进程上下文换入内存。交换功能由进程0完成。在系统初始化结束0(因为初始化结束时内存总不会是满的),内存不够时出进程。如果没有进程要换入换出时,则该进程进入睡眠状态。系统通过时钟中断定期唤醒进程0完成交换功能。在进程0执行之前,时钟中断处理程序计算出每个就交换算法实际上涉及三个部分:外存交换设备的sched过程完成进程的换入与换出。至于外存交换sched过程的流程图如图6.13所示图6.13sched过程流程在图6.13中d程序首先检查oc结构表,寻找一个不在内存且驻留时间最长的就绪态进程。如果该进程在外存交换区的驻留时间小于2秒,则表示没有适当的进程可以换入,从而设置runout标识后进入睡眠状态。反之,如果d过程找到了一个适当的就绪态进程,则启动输入输出设备,将其写入内存。如果内存中没有足够的内存空间(这可由存储表知道),则d过程按照换出算法寻找在内存中的进程换出。换出策略是:首先,锁定位已经锁住的进程不能换出;其次,先换出那些已部分换出的进程(在正文段被共享时,如果一个进程的正文段随同该进程被换出了的话,则共享该正文段的进程变成已部分换出的进程),然后选择睡眠或暂停状态中优先数最大的,最后选择就绪进程中已在内存时间最长者。间不得少于2秒。如果sched过程在内存中找不到合适的进程换出,则设置runin标识,表示外存有runin标识后,sched过程调用sleep过程,进程0当有合适进程可以换出时,或内存中有足够空间存在时,d过程将反复地把所有符合换入条件的进程换入内存,直到外存交换区不存在可以换入的进程或内存中没有可以换出的进程时为止。另外,在XtemⅤ中,除了使用d过程将内存中的进程换出内存之外,还可以通过一个称为特别进程0的进程调用xsched过程将进程换出。UNIXSystemⅤ中的进程通信分为三个部分:低级communacation)。近年来,UNIXSystem的改TCP/IP协议并提供了相应的系统调用接口。UNIX的低级通的低级通信主要用来传递进程间的控制信号。实现传递控制信号的方法有两种。一种是利用睡眠原语sleep和唤醒原语wakeup实现进何信息,比P,V原语操作更低级。sleep原语使另一种是利用软中断信号实现同一用户的诸进程之间的通信。目的是通知对方发生了异步事件。temⅤ中有19个软中断信号,作用见图6.14。软中断是对硬件中断的一种模拟,发送软中断就是向接收进程的oc结构中的相应项发送图6.14中的一个信号。如果用户进程发送的软中断号大于19,则接收进程不予理睬,从而发送无效。接收进程在收到软中断信号后,将按照事先的规定去执行一个软中断处理程序。但是,软中断处理程序不像硬中断处理程序那样,收到中断信号后立即被启动,它必须等到接收进程执行时才能生效。另外,一个进程自己也可以向自己发送软中断信号,以便在某些意外的情况下,进程能转入规定好的处理程序。例如,大部分陷阱都是由当前进程自己向自己发送一个软中断信号而立即转入相应处理的。软中功软中断功1远地用户挂段违2键盘打入DELETE系统调用3键盘打QUITPIPE文件只有写4指信5断点或指软件终止6IOT指用户定7EMT指用户定8浮点溢子进程消9要求终止电源失总线超图6.14UNIXSystem中断信用的进程控制。例如,利用sleep和wakeup,可以实现系统中对互斥资源的管理和进程间的同步。当进程要使用临界资源时,先检测相应的锁定标志,若锁定标志已置位,则调用p进入睡眠。直到其他进程退出临界区后释放了锁定标志。如果系统调用keu唤醒等待该资源的进程,该进程才有进入临界区的可能。读者可以自行用C语言或形式化语言描述出用p和p实现同步或互斥的过程。为了给用户进程也提供相应的同步、互斥以及软中断通信功能,X系统提供了几种相应的系统调用和实用程序。一种是用于互斥的实用程序,其格式是:lockf(fd,function其中,fd是被锁定文件标识,fun是控制值,可取值:0,1,2,3。1表示锁定一个程序段,0表示不再锁定,而2则测试和锁定一个程序段,3则用来测试待锁定的程序段是否已被其他进程锁定。e表示自fd文件的e个相连字节之后开始锁定程序段。如果e等于零,则表示从调用lockf后开始锁定。wait()用于父子进程之间的同步,而sleep则使得当前进程睡眠n秒后自动唤醒自己。系统调用sig)和()被用来传递和接收软中断信号。一个用户进程可调用pid,sig)向另一个标识号为d的用户进程发送软中断信号sig。根据图6.14可知,用户可以定义的软中断号是16或17。另外,标识号为d的进程通过signal(sg,fun)捕捉到信号g之后,执行预先约定的动作fun,从而达到这两个进程的通信目的。一个经常用到的例子是(,SIG-,表示当前进程不做任何指定的工作而忽略键盘中断信号的影响。进程间通信IPC是UNIXSystemⅤ的一个程序包,它负责完成SystemⅤ进程之间的大量数据传送工作。在IPC包被开发出来之前,通信能力一直是UNIX统的一个弱点,因为只能利用pipe来传递大量数据而pipe又存在着只有调用pipe的进程的子孙能使用它进行通信的缺点。虽然有名管道能使非同族进程之间相互通信,但它们不能复用一个有名管道以便为多对通信进程提供私用通道。也就是说,有名管道不能识别其通信伙伴,也不能有选择地接收信息。C程序包解决了这些弱点。UNIXSystemIPC软件包分三个组成部分消息(message)用于进程之间传递分类的格式化数据。共享器(edmemory)方式可使得不同进程通过共享彼此的虚拟空间而达到互相对共享区操作和数据通信的目的。信号量(oe)机制用于通信进程之间往前推进时的同步控制。信号量总是和共享器方式一起使用。由于上述三种方式在UNIXSystem中是作为一个整每种机制都用两种基本数据结构来描述该机制。即:①索引表:其中一个表项由关键字、控制结构及操作状态信息组成。每个索引表项描述一个通信实例或通信实例的集合。②实例表:一个实例表项描述一个通信实例的有关特征。例如,消息机制中消息队列表相当于索引表,而消息头表则相当于实例表,如图6.15。索引表项中的关键字是一个大于零的整数,它由用户选择名字。索引表的控制结构中含有创建该表项进程的用户id和用户组id。由后述“contol类系统调用,可为用户和同组用户设置读-写-执行权,从而起到通信保护的作用。每种通信机制的“contol”类系统调用可用来查询索引表项中的状态,以及置状态信息或从系统中删除表项。图6.15索引表与实例表的关除了“contol”类系统调用之外,每种通信机制还含有一个“get”类系统调用,以创建一个新的索引表项或者用于获得已建立的索引表项的描述字。每一种索引表项都使用下列公式计算索引表项的描述字:描述=索引表长度×分配序号+索引表项下标例如,如果消息队列表长100,表项1的描述字可以是100×(分配序号)+1=1、101、201等。这做的好处是,当进程释放了一个旧的索引表项,且该索引表项又分配给另外的进程时,因为分配序号的增加将使得描述字改变,从而原来的进程不可能再次该表项。由此,可以起到通信保护作用。其他系统调用索引表项时的索引值为描述字(索引表长度)下面,简单地介绍三种通信机制的系统消息机消息机制提供四个系统调用。msgqid=msgget(key,msg)key-tkey; msgmsgctl(msgqid,cmd,buf) msgqid,cmd;msgqid-ds#buf;msgsnd(msgqid,msgp,msgsz,msg) msgqid;structmsgbuf*msgp; msgsz,msg 以及msgrcv(msgqid,msgp,msgsz,msgtyp,msg) msgqid;structmsgbuf*msgp; msgsz; msgtyp; msg;这些系统调用所需要的数据结构和表格都放<sys/types.h>,<sys/ipc.h>和<sys/msg.h>中。此,在使用各种通信机制的系统调用之include这三个头文件系统调用msgget返回一个消息描述字msgqid,msgqid指定一个消息队列以便其他三个系统调用使用。y和ms具有获取的语义。y可以等于关键字-PRITE,以保证返回一个未用的空表项,y还可以被设置成一个还不存在表项描述字的表项号。这时,只要msh&-T为真,则系统会生成一个新的表项并返回描述字。例如,msgqid=msgget(MSGKEY,0777)在MSGKE所对应的消息队列表项不存在时,将创建该表项,在MSGKE所对应的表项存在时,msgget返回该表项的描述字。系统调用msgctl用来设置和返回与msgqid相关联的参数选择项,以及用来删除消息描述符的选择项。cmd的取值范围为-T,IPC-,IPC-RMID}。其中,IPC-SET表示将指针为buf中的用所有当前值读入buf所指的用户结构中;而IPC-队列表项。buf是用户空间中用于设置或消息消息。msgsnd(msgqid,msgp,msgsz,msg)中的是用户消息缓冲区指针;msgsz是消息正文的长度;系统调用msgev中比msgsnd多一个参数msgtyp,它规定接收消息的类型。msgtyp=0时,表示接收与msgqid相关联的消息队列上的第一个消息;msgtyp>0时,表示接收与msgd相关联的消息队列上msgty类型的第一个消息;而msgtyp<0时,则表示接收小于或等于msgtyp绝对值的最低类型的第一个消息。另外,ms指示当与msgqid相关联的消息队列上无消息时系统应当怎么办。例如,图6.16和图6.17分别给出了用C语言编写的,由顾客进程和服务者进程调用的程序例子。#include〈sys/types.h〉#include〈sys/ipc.h〉#include〈sys/msg.h〉 MSGKEY75strucumsgform{longmtypecharmtext[256]main({struct msg msgqid,pid,*pintmsgqid=msgget(MSGKEY,0777); pid=getpid();pint=(int*)msg.mtext*pint=pidmsg.mtype=1; msgsnd(msgqid,&msg,sizeof(int),0);/*往msgqid发送消息msg*/msgrcv(msgqid,&msg,256,pid,0); printf("client:receivefrompid%d\n",*pint);}图6.16顾客进程的程序#include〈sys/types.h〉#include〈sys/ipc.h〉#include〈sys/msg.h〉 MSGKEY75structmsgform{longmtypecharmtext[256]}msg msgqid;main(){ i,pid,*pintexterncleanup()for(i=0;i<20;i++) signal(i,cleanup);msgqid=msgget(MSGKEY,0777|IPC-CREAT); for(;{msgrcv(msgqid,&msg,256,1,0); /*接收来自顾客进程的*/pint=(int*)msg.mtext;pid=*pint;printf("server:receivefrompid%d\n",pid)msg.mtype=pid*pint=getpid()息}
msgsnd(msgqid,&msg,sizeof(int),0);/*发送应答}cleanup{msgctl(msgqid,IPID,0);exit();}图6.17服务者进程的程序图6.16是顾客进程。该进程向服务者进程发送一个含有进程号d以及类型为1的消息,向服务者进程发出服务请求。然后,从服务者进程接收相应的回答或服务。在图6.17中,MSGK是用户自己定义的关键字,已在本节前面部分做过说明。而msgfor则是用户自定义的发送消息正文和消息类型,这一消息被定义为256字节长。紧接着,顾客进程首先使用系统调用msgget创建,或得到与关键字MSGKE相关联的消息队列描述字msgqid,并由库函数getpid()得到该进程I。接下去是对消息正 类型转换,以便计算消息长度并将进程ID 到消息正文中最后,顾客进程调用msgsnd把消息msg挂入以msgqid为描述字的消息队列,并从该队列接收服务进程发往该进程的第一个消息(用进程号d作消息类型)。图6.17是服务者进程。该进程首先检查是否捕捉到由l发来的软中断信号。如果捕捉到时,则调用函数cleanup从系统中删除以msgd为描述字的消息队列。如果它捕捉不到软中断信号或者接收的是不能捕捉的)信号,则该消息队列继续保留在系统中,而且在该队列被删除以前试图以该关键字建立新消息队列的尝试都会失败。然后,服务者进程使用系统调用msgget,并在msgget中置位T来建立一个消息队列结构。紧接着,服务者进程接收所有类型为1的,也就是从顾客进程来的请求消息。这是由系统调用msgcv完成的。在接收到消息之后,服务者进程从消息中读出顾客进程的I,并将返回的消息类型置为顾客进程的I。然后,服务者进程把要发送的消息到消息正文域中,并使用msgsnd将消息挂入msgqid为描述字的消息队列。本例中,由服务者进程发送给顾客进程的消息也是服务者进程的ID。在消息机制中,消息被格式化为类型与数据对,且允许不同的进程根据不同的消息类型进行接收,这是使用管道通信所无法办到的。共享区机 ①建立新的共享区或返回一个已存在的共享区 flag)。其中,key是用②将物理共享区附接到进程虚拟地址空间的调用t(shmid,add,flag)。其中,d是t返回的共享区描述字,而add是将共享区附接到其上的用户虚拟地址,当addr等于零时,系统自动选择适当地址进行附接(默认)。flag规定对此区是否是只读的,以及是否应对用户规定的地址作舍入操作。t返回系统附接该共享区后的虚拟地址。③进程从其虚拟地址空间断接一个共享区的系统调用shmdt(addr)。其中,addr是shmat返回的④查询及设置一个共享区状态和有关参数的系统调用(,cmd,buf)。其中,d是共享区的描述字,cmd规定操作类型,而uf则是用户数据结构的地址,这个用户数据结构中含有该共享区的状态信息。接以及断接共享区。共享区的好处在于为通信进程提供了直接通信的,使得通信进程可以直接彼此的某些虚拟空间。图6.18给出两进程共享区的示意图图6.18共享区示意一个共享区建立后可以被附接到一个进程的多个虚拟区间上,而一个进程的虚拟空间也可以附接多个共享区。 图6.19和图6.20分别给出了将进程附接到共享区上,以及进程间共享区的C语言程序实例。在图6.19中,该进程建立了16K字节的共享区, 区的起始单元开始,顺序写入0到255个自然数。如果该进程捕捉到一个软中断信号(除外),则由系统调用l删除该共享区。#include〈sys/types.h〉#include〈sys/ipc.h〉#include〈sys/shm.h〉 intshmid;main(){ i,*pint; *addr;externchar*shmat();externcleanup();for(i=0;i<20;i++) /*软中断处*/signal(i,cleanup);shmid=shmget(SHMKEY,16*K,0777|IPC-CREAT)/*建立16K共享区SHMKEYaddrshmat(shmid,0,0);/*共享区首地*/printf("addr0x%x\n",addr);pint=(int*)addr;for(i=0;i<256;i++)*pint++=ipintint*)addr/*共享区第一个字中写入长度256,以便*pint=256pause /*等待接收进程}cleanup({shmctl(shmid,IPID,0);exit();}图6.19共享区程序实#include〈sys/types.h〉#include〈sys/ipc.h〉#include〈sys/shm.h〉 shmid;main(){inti,*pint; *addrexternchar*shmat()shmidshmget(SHMKEY,8*K,0777);/*取共享区addrshmat(shmid,0,0)/*连接共享区pint=(int*)addrwhile(*pint==0);/*共享区的第一个字节为零时,等待*/for(i=0;i<256;*pint++) printf("%d\n".*pint++)}图6.20共享区程序实储区的不同总量,图6.20中只取 区的8K字节该进程等待着直到图6.19中进程在共 区中信号量机信号量机制是基于第3章所述的P、V原语SystemⅤ中一个信号量由以下几部分组成①信号量的值,一个大于、小于或等于零的②最后一个信号量的进程的进程id③等待着信号量值增加的④等待着信号量值等于零的进程数信号量机制提供下列系统调用对信号量进行创建、控制、以及P、V操作。它们是:于产生一个信号量数组以及得以存取它们的系统调用semget(semkey,count,flag)。其中,semkeysemkey是用户指定的关键字,count规定信号量数semid=semget(SEMKEY,2,0777|IPC-CREAT)创建一个关键字为的含有两个元素的信号量数组。图6.21信号量数系统调用semop(semid,oplist,count)。其中,semid是semget返回的描述字,oplist是用户提供的操作数组的指针,count是该数组的大小。semop返回在该组操作中最后作的信号量在用户定义的操作数组中的每个元素包含三个内容,它们是信号量序号、操作内容(对信号量进行P操作或V操作的值)、标识。一个数组可同时包含对n(n>1)个信号量的操作。p根据操作数组所规定的操作内容改变信号量的值。如果操作内容为正数(V操作),则它将该信号量增加该操作内容的值,并唤醒所有等待此信号量值增加的进程。如果操作内容为零,则检查信号量的值,若为零,p执行对同一操作数组中其他信号量的操作;否则,废弃本次系统调用所完成的所有信号量操作之后,调用p使该进程进入睡眠状态。如果操作内容是负数且绝对值小于等于信号量值,则p从信号量值中减去操作内容;否则,调用p让该进程睡眠在等待信号量值增加的事件上。例如:struct unsignedshort sem-num; sem-op; sem-}Psembufsemid=semget(SEMKEY,2,0777);Psembuf.sem-num=first;Psembuf.sem-op=-1;Psembuf.sem-=SEM-UNDO;semop(semid,&psembuf,1)定义了一个对二元信号量数组中第一个信号量的P操作。其中,M-是为了保证P操作的原子性而设置的标识。信号量进行控制操作的系统调用semctl(semid,number,cmd,arg)。其中,semid是semget返回的信号量的描述字,number是对应于semid的信号量数组的序号,cmd是控制操作命令,arg是控制操作参数,是一个union结构:unionsemun valstructsemid-ds*buf;unsignedshort*array;}arg系统根据cmd的值解释arg,并完成对信号量的删除、上面介绍了有关C的三种通信机制。这三种机制使用消息和共享 区方式使多个进程使用同一质(消息队列或共享 区)进行通信。这优于道等通信方式。但是,由于各系统调用中使用的关键字的语义很难扩展到一个网络上(不同的机器上同一关键字可以描述不同的对象),因此,C仍是属于单一机器环境下的通信机构。UNIX管如前所述,管理极大地影响进程调度和控制,因为调度程序不调度一个只有oc结构在内存的进程执行。然而,内存是一种有限的资源,无法容下全部活动进程。管理系统必须决定哪个进程的哪个部分应该放在内存,并管理那些不在内存又属于同一进程虚空间的部分。因此,X系统必须解决为进程分配内存空间、进行内存扩充、以及完成由虚存到物理器的地址变换,和内存信息保护与共享等问题。UNIXSystemⅤ采用请求调页和交换策略进行存扩充。交换技术与请求调页策略的主要区别在于:交换技术换进换出整个进程(oc结构和共享正文段除外),因此,一个进程的大小受物理器的限制;而请求调页策略在内存和外存之间来回传递的是 页而不是整个进程,从而使得进程的地址具有了更大的灵活性,且允许进程的大小比可用物理 空间大得多。在本章前面有关X进程调度部分,已对X系统的交换策略作了介绍。这里,主要介绍请求调页策略时的 管理技术。内存管理是基于一定的硬件基础的,本节以VAX-11机为例,说明SystemⅤ的地址空间划分和管理空间的程序段P0、控制段P1、系统空间的区和每个区都有自己的页表。每个页表的长度和起始地址分别由相应的长度寄存器和基址寄存器描述。图6.22VAX-11机虚存空间画另外,除了以功能分区以外,-1的地址空间又被画分成以512字节为1页的线性数组,页的编码范围为(0~223-1),如图6.23所示。 字字节偏移虚页图6.23VAX-11机虚拟地址构字节为一个页面的线性数组。页面的编(0~221-1),如图6.24所示。在图6.23的虚拟地结构中,高两位,也就是30位和31位是用作区分功能区的,例如00表示该页在P0区,而01表示该页在1区,而10则表示该页在系统区。3130 页面字节偏移31 2726 21 VM物理页面号图6.25页表项内其中,第31位(最)是有效位,如果该位(V)=1,则表示该虚页所对应的内容在内存中,且第0~第20位所对应的是该虚页的页面号。0时,则该虚页不在内存,硬件将产生相应的出错信息并转由操作系统处理。第30位至27位是保护位,它们指明不同的处理机访问模式下,对该页面的读写操作权。第26位M是修改位,在内存中,第一次对该页面进行写操作修改该页面内容后,要将该位置1,以便将其换出时写回磁盘保存信息。如果M=0,则由于磁盘上保存有该页副本,从而换出时不必写回外存而减少不必要的I/操作。另外,有的系统中还设置有位R和位A等。其中R指示最近是否有进程过该页,而A则记录该页在内存中驻留的时间。R和A都是用于请求在-1中,XtemⅤ把正文段、数据段以及页表全部放入区,并在系统初始化时使其常驻内存的低地址部分。区虚拟地址空间与物理空间的对应关系如图6.26。页表和诸进程页表在物理上是一块连续区。这些页表覆盖整个物理空间。存器的SBR和SLR中,它们在操作系统被引导启图6.26系统虚空间及内存空与页表相对应,每个进程的0区和1区也有自己的页表。正如图6.26所示的那样,各进程页表都在虚存空间分得一段连续的虚存区。由于虚存空间被所有用户进程共享,所以两不同进程的页表不能有相同的虚存地址。这也正如在段页式管理中每个段必须有唯一的段名一样。当前执行进程的0区和1区的页表虚存始址存放在相应的基址寄存器0R,1R和页表长度寄存器0,1中。 页表和进程各区页表在内存中的逻辑关系如图6.27所示。当前执行进程的0R,1R,P0和1R的内容在进程调度发生进程上下文切换时装入。显然,在进程空间地址变换时,为了得到进程页表所指的实际物理地址,U至少得器两次。图6.27内存中页表与进程页表的逻辑关UNIXSystemⅤ对内存中的页表区和P0区与P1区采用了不同的分配释放方法。对于页表区,采用的是分区式管理中的最先适应算法(firstfit);而对下面进一步讨论System的内存分配与释放、地址UNIXSystem系统中的进程是由父进程根据需要动态生成的,每个进程都享有自己的虚拟空间。所以,在生成一个子进程时,系统为该子进程建立自己的虚拟空间。具体地说,就是为子进程分配页表项(包括0区、1区的页表以及页表中的页表项)并使之与系统虚拟空间相对应。然后,再为子进程分配内存页面存放0区和1区的程序和数据代码。从而,内存空间的分配实际上变成了两个问题,即P0区和P1区页表的分配和得到在虚拟地址空与此相对应,内存的释放也变成了进程P0区与P1区页表的释放以及进程P0区与P1区的释放进程页表的在XSystemⅤ中,页表区的分配使用了分区式管理的最先适应分配算法。这是因为整个进程页表区在虚拟地址空间和内存中是连续的,而且进程页表常驻内存,变化较少,使用最先适应算法既可满足系统管理的需要,又有较少的系统开销。sptalloc和sptfree。其中sptalloc和sptfree分别调用malloc和mfree,因此,可以说进程页表的分配释malloc的原理可简述如下(请参照第5章分区式管理中的有关部分):系统内页表区按空闲区的地址,从低到高成一个自由链式分区可用表map。其中每个表项包含两个元素,一个是该空闲区的页面数(或者是可登记项的项数)siz,另一个是空闲区页表在页表表项中所对应的索引脚标add。显然,由索引脚标add,可以得到该页表对应的系统虚存空间始址dspt。以自由链map的头指针p和所要求的页面数或表项数e作输入参数,在map中一旦搜索到一个大于或等于e的空闲页表区,则将它分配给所要求进程和调整自由链,然后再返回索引脚标add。以上就是malloc的原理。除了用于内存页表区分配之外,malloc还适用于交换区的分配。mfree的原理可简述如下(请参考第5章分区释放与合对于所要释放页表的大小e及起始号a,从map链的头指针出发,按起始号大小链中相应的位置。如果所释放的页表区前后有空闲区存在的话,则进行相应的合并(合并方法参见第5章)后再调整map链并返回。同理,mfree也用来进行交换区等释放空闲区P0区与P1区的内存分配与释在系统空间及在内存的相应区中,有一个内存位示图。该位示图就是用来进行各进程的进程区内存分配与释放管理的。位示图的每一位表示一个物理页面的使用情况,当对应页面已被分配时,该位为1,否则为0。位示图的大小由内存的大小和页面的大小所决定,一个容量为16M和每页512字的内存将有一个4字节大小的位示图。显然,对于区那些常驻内存的固定部分,其位示图的对应位也是固定的,因而可以不要地址变换机构。在temⅤ中,位示图所对应的内存首地址是memvad。由于位示图一般具有几字节,而在进程执行期间,页面的更换又相当频繁,如果每次页面更换都必须扫描整个位示图,则显然会大大影响执行效率。为此,系统设置了一个长度为100的me结构,以减少扫描位示图的次数。该结构包含下列元素:{ m-free;/*空闲页面数,P-num中存有页面号的最大下/*最低页/*/*上次查找memvad结束时的指针/*内存中的空闲页面数shortm-pnum[NICMEM]; 多NICMEM=100*/}用于内存管理的函数有二个:即memall和memfe。内存页面的分配由memal完成,而内存页面的释放则由memfe完成。memall和memfe二者都使用上述数据结构进行页面分配和释放。memall的调用形式为:memall(ba)。其中,bas为欲填入页面号的页表始址,而e是申请分配的内存页面数。若没有则返回零值。否则,它直接从m-pnum中取出size个空闲页面把memvad表中相应位置成中,然后再分配,从memvad表中查找未分配的页面号不是每次都从头开始,而是从-ptr的当前位置开始向后查找。当到达内存最后一个页面-hi时,再从第一个页面-lo开始重新分配。每分配一个页面,便把相应的页面号填入bas所的页表中。最后,返回实际分到的页面数。地址变地址部分,首先介绍区的地址变换。区地址变页式管理的基本地址变换过以下几步组成装配页表基址寄存器SBR和长度寄存器SLR把虚拟地址中的虚页号和R的内容相加得到相应的页表项将页表项中所对应的内存页面号与页内偏移值相加,得到所要的物理地址。以上各步由硬件自动考虑到内存保护等功能之后的区地址变换过程如图6.28所示。图6.28区地址变进程空间地进程空间(包括P0区和P1区)的地址变换过程比区在于区的页表起始地址,因此,进程上下文切心区的虚拟地址。因此,硬件必须首先使用页址变换至少要比区的地址变换多一次内存,经常使用的页表项副本请求调页技该页只能在下述三种介质的任一种之中(1)在外存交换区中(2)在外存可执行文件中,(3)在入输出缓冲区的空闲队列中,针对这三种不同的情况,系统除了要在内存中分配或淘汰相应的页面以调入这些页之外,还要正确区分这些页所在的位置,以便迅速地将所需要的页调入内
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 麻醉药品和精神药品的管理与使用
- 工匠精神赋能创新创业教育与实践
- 精神的三间小屋句子赏析
- 厨师长管理培训
- 检验科体液检查操作流程规范
- 工匠精神开学第一课
- 管理书籍设计展示
- 2026河北沧州任丘关爱精神病医院招聘备考题库附完整答案详解【必刷】
- 2026中煤财务有限责任公司招聘2人备考题库及答案详解(新)
- 2026广东东莞市望牛墩镇中心幼儿园招聘备考题库【夺分金卷】附答案详解
- 进入刘才栋教授示范教学 - 局部解剖学 - 复旦大学上海医学院
- 常用卧位摆放护理操作考核标准、流程与指引
- 2023年安徽省中学生生物学竞赛预赛试卷-完整版
- 基坑开挖风险评估报告
- 水生动物增殖放流技术规范
- 纪委办公室室内改造项目可行性研究报告
- GB/T 17880.6-1999铆螺母技术条件
- SB/T 11094-2014中药材仓储管理规范
- GB/T 23339-2018内燃机曲轴技术条件
- 实验12土壤微生物的分离及纯化课件
- 2022年4月自考00402学前教育史试题及答案
评论
0/150
提交评论