进程、
当我们在一个现代系统上运行一个程序时,会得到一个假象,就好像我们的程序是系统中当前运行着的唯一的程序。我们的程序好像是独占地使用处理器和存储器。处理器就好像是无间断地一条接一条地执行程序中的指令。最后,我们程序中的代码和数据好像是系统存储器中唯一的对象。这些假象都是通过进程的概念提供给我们的。
进程的经典定义就是一个执行中的程序的实例。系统中的每个程序都是运行在某个进程的上下文(context)中的。上下文是由程序正确运行所需的状态组成的。这个状态包括存放在存储器中的程序的代码和数据,它的栈、通用目的寄存器,浮点寄存器的内容、程序计数器、环境变量、以及打开文件描述符的集合。进程提供给应用程序的关键抽象:
- 一个独立的逻辑控制流,它提供一个假象,好像我们的程序独占地使用处理器。
- 一个私有的地址空间,它提供一个假象,好像我们的程序独占地使用存储器系统。
逻辑控制流、
假如我们用调试器来控制程序单步执行,我们会看到一系列程序计数器PC的数值,这些数值与可执行程序中的指令是一一对应的,我们把这个PC值的序列叫做逻辑控制流,简称逻辑流。
下图是一个运行着三个进程的系统,单核处理器。处理器的一个物理控制流分成了三个逻辑流,每个进程一个。每个竖直的条表示一个进程的逻辑流的一部分。在这个例子中,三个逻辑流的执行是交错的。进程A运行了一会儿,然后是进程B开始运行到完成。然后,进程C运行了一会,进程A接着运行直到完成。最后,进程C可以运行到结束了。

这张图描述了不同进程之间轮流使用处理器的情况,每个进程指令逻辑流的一部分,我们把一个逻辑流的执行在时间上与另一个流重叠的情况称为并发流。两个流的执行称为并发运行,例如进程A和进程B是并发运行的,同样A和C也是。不过B和C不是并发运行的,这是因为C执行前B已经执行完了,所有二者不是并发运行。
并发和并行这两个概念不相同。并行是两个进程在不同的处理器核上同时运行,并发是在同一个处理器核上交替运行。
私有地址空间、
进程也为每个程序提供一种假象,好像它独占地使用系统地址空间。在一台有n位地址的机器上,地址空间是 2n 个可能地址的集合, 0,1,...2n−1 。一个进程为每个程序提供它自己的私有地址空间。一般而言,和这个空间中某个地址相关联的那个存储器字节是不能被其他进程读或者写的,从这个意义上说,这个地址空间是私有的。
尽管和每个私有地址空间相关联的存储器的内容一般是不同的,但是每个这样的空间都有相同的通用结构。如下图展示了一个x86 Linux进程的地址空间的组织结构:地址空间底部是保留给用户程序的,包括通常的文本、数据、堆、和栈段。地址空间顶部是保留给内核的。地址空间的这个部分包含内核在代表进程执行指令时(比如,当应用程序执行一个系统调用时)使用的代码、数据和栈。


用户模式和内核模式、
为了使操作系统内核提供一个无懈可击的进程抽象,处理器必须提供一种机制,限制一个应用可以执行的指令以及它可以访问的地址空间范围。
处理器通常是用某个控制寄存器中的一个模式位(mode bit)来提供这种功能的,该寄存器描述了当前进程享有的特权。当设置了模式位时,进程就运行在内核模式中(有时叫做超级用户模式)。一个运行在内核模式的进程可以执行指令集中的任何指令,并且可以访问系统中任何存储器位置。没有设置模式位时,进程就运行在用户模式。用户模式中的进程不允许执行特权指令(privileged instruction),比如停止处理器、改变模式位,或者发起一个I/O操作。也不允许用户模式中的进程直接引用地址空间中内核区的代码和数据。任何这样的尝试都会导致致命的保护故障。反之,用户程序必须通过系统调用接口间接地访问内核代码和数据。运行应用程序代码的进程初始化时是在用户模式。进程从用户模式变为内核模式的唯一方法是通过诸如中断、故障、或者陷入系统调用这样的异常。当异常发生时,控制传递到异常处理程序,处理器将模式从用户模式变为内核模式。异常处理程序运行在内核模式中,当它返回到应用程序代码时,处理器就把模式从内核模式改回用户模式。
上下文切换、
操作系统内核使用一种称为上下文切换(context switch)的较高层形式的异常控制流来实现多任务。上下文切换机制是建立在已经讨论过的那些较低层异常机制之上的。
内核为每个进程维持一个上下文(context)。上下文就是内核重新启动一个被抢占的进程所需的状态。它由一些对象的值组成,这些对象包括通用目的寄存器、浮点寄存器、程序计数器、用户栈、状态寄存器、内核栈和各种内核数据结构,比如描绘地址空间的页表、包含有关当前进程信息的进程表,以及包含进程已打开文件的信息的文件表。
在进程执行的某些时刻,内核可以决定抢占当前进程,并重新开始执行一个先前被抢占的进程。这种决定就叫做调度(schedule),是由内核中称为调度器(scheduler)的代码处理的。当内核选择一个新的进程运行时,我们就说内核调度了这个进程。在内核调度了一个新的进程后,它就抢占当前进程,并使用一种称为上下文切换的机制将控制转移到新的进程。
上下文切换三步:(1)保存当前进程的上下文(2)恢复某个先前被抢占的进程被保存的上下文(3)将控制传递给这个新恢复的进程
Comments NOTHING