操作系统精髓与设计原理(原书第6版)——学习笔记(5)



附录1B 过程控制

         控制过程调用和返回的最常用的技术是使用栈。

栈的实现

         栈是一个有序的元素集合,一次只能访问一个元素,访问点称做栈顶。栈中的元素数目,或者栈的长度是可变的。只可以在栈顶添加或删除数据项。基于这个原因,栈也称做下推表或后进先出(LIFO)表。

         栈的实现需要有一些用于存储栈中元素的单元集合。图1-25给出一种典型的方法,在内存(或虚拟存储器)中为栈保留一块连续的单元。大多数时候,快中只有一部分填充着栈元素,剩余部分供栈增长时使用。正确操作需要三个地址,这些地址通常保存在处理器寄存器中。

  • 栈指针:包含栈顶地址。如果往栈中添加(PUSH)或删除(POP)一项,这个指针减1或加1,以包含新的栈顶地址。

  • 栈地:包含保留块中最底层单元的地址。当往一个空栈中添加一项时,这是所用到的第一单元。对一个空栈进行POP操作,则会发生错误。

  • 栈界限:包含保留块中另一端,即顶端单元的地址。如果对一个满的栈进行PUSH操作,则发生错误。

传统上,以及现在的大多数机器中,栈地是保留的栈块的高端地址,而栈界限是低端地址。因此栈是从高端地址向低端地址增长的。

操作系统精髓与设计原理(原书第6版)——学习笔记(5)_第1张图片

过程调用和返回

         管理过程调用和返回的最常用的技术是使用栈。当处理器执行一个调用时,它将返回地址放在栈中;当执行一个返回时,它使用栈顶的地址。对于图1.26中的嵌套过程,图1.27显示了栈的使用情况。

        

         在过程调用时,通常还需要传递参数,可以把它们传递到寄存器中。另一种可能的方法是把参数保存在存储器中的Call指令之后,在这种情况下,参数后面必须是返回单元。这两种方法都有缺陷,如果使用寄存器,被调用程序和调用程序都必须被写入,以确保正确使用寄存器;而在存储器中保存参数,则很难交换可变数目的参数。

         更灵活的参数传递方法是栈。当处理器执行一次调用时,不仅在栈中保存返回地址,而且保存传递给被调用过程的参数。被调用过程中从栈中访问这些参数,在返回之前,返回参数可以放在栈中返回地址的下面。为一次过程调用保存的整合参数集合,包括返回地址,称作栈帧(stack frame)。

         1.28给出一个例子,过程P中申明了局部变量x1x2,过程P调用过程QQ中声明了局部变量y1y2。存储在每个栈帧中的第一项指向前一帧的指针,如果参数的数量与长度是可变的,就需要用到该指针。第二项是相应于该栈帧的过程的返回点。最后,在栈帧的顶部为局部变量分配的空间。局部变量可用于参数传递。例如,假设在P调用Q时,它会传递一个参数值,该参数值可存储在变量y1中。因此在高级语言中,P例程中的一个指令看起来会如下所示:CALL Q(y1)

         执行该调用时,会为Q创建一个新的栈帧(图1.28b所示),这包含一个到P的栈帧的指针、到P的返回值以及Q的两个局部变量,其中一个被初始化为由P传递的参数。零一个局部变量y2是由Q在计算过程中使用的局部变量。

可重入过程

         可重入过程是指程序代码的一个副本在同一段时间内可以被多个用户共享使用。可重入有两个重要特征:程序代码不能修改其自身、每个用户的局部数据必须单独保存。一个可重入过程可以被中断,由一个正在中断的程序调用,在返回该过程时仍能正确执行。在共享系统中,可重入可以更有效地使用内存:程序代码的一个副本保留在内存中,有多个应用程序可以调用这个过程。

         因此,可重入过程必须有一个永久不变的部分(组成过程的指令)和临时部分(指向调用程序的指针以及指向程序所使用的局部变量的存储地址指针)。过程的每个执行实例称作激活(activation),将执行永久部分的代码,但拥有自己的局部变量和参数的副本。与特定的激活相关的临时部分称作激活记录。
        
支持可重入过程最方便的方法是使用栈。当调用一个可重入过程时,该过程的激活记录保存在栈中。这样,激活记录就成为过程调用所创建的栈帧的一部分。

你可能感兴趣的:(栈,过程控制,过程调用与返回,可重入过程)