[翻译] Operating System-There Easy Pieces 4.进程的抽象

进程的抽象

在本文中,咱们将讨论操做系统为用户提供的最基本的抽象之一:进程。 非正式地定义一个进程很是简单:它是一个正在运行的程序。程序自己是一个没有生命的东西:它只是存储在磁盘上的一堆指令(也许还有一些静态数据),等待开始行动。 操做系统采用这些字节并使它们运行,将程序转换为有用的东西。算法

事实证实,人们常常想要同时运行多个程序; 例如,您可能但愿在笔记本或者PC上同时运行Web浏览器,邮件程序,游戏,音乐播放器等应用。 事实上,典型的系统彷佛能够同时运行数十甚至数百个进程。 这样作使系统易于使用,不须要关心CPU是否可用,只须要运行程序就行。 所以咱们存在的挑战是:shell

问题的关键:数组

如何提供许多CPUS的错觉?浏览器

虽然只有少数物理CPU可用,但操做系统如何提供几乎无穷无尽的CPU供应的错觉?网络

 

操做系统经过虚拟化CPU来建立这种错觉。经过运行一个进程,而后中止它并运行另外一个进程,这样一直轮换执行,操做系统能够制造出存在许多虚拟CPU的错觉。而实际上只有一个物理CPU(或少数几个)。这种基本技术称为CPU的时间共享(时间片),容许用户运行任意数量的并发进程。潜在的成本是性能损耗,由于若是必须共享CPU,每一个进程都会运行得更慢。数据结构

为了更好的实现CPU的虚拟化,操做系统既须要一些低级措施,也须要一些高级策略。咱们称这些低级措施为“机制”。机制是实现所需功能的低级功能的方法或协议。例如,咱们将在下面学习如何实现上下文切换,这使操做系统可以中止运行一个程序并在给定的CPU上开始运行另外一个程序。全部现代操做系统都采用这种分时机制。并发

除了这些机制以外,还以策略的形式存在操做系统中的一些智能算法。策略是在OS中作出某种决定的算法。例如,给定在CPU上运行的许多可能的程序,OS应该运行哪一个程序?操做系统中的调度策略将作出此决定,可能使用历史信息(例如,哪一个程序在最后一分钟运行得更多?),工做负载知识(例如,运行的程序类型)和性能指标(例如,系统是否优化交互性能或吞吐量?)来作出决定。函数

 

提示:使用时间共享(和空间共享)性能

时间共享是操做系统共享资源的最基本技术之一。 经过容许资源被一个实体使用一段时间,而后稍微使用另外一个实体,等等,所讨论的资源(例如,CPU或网络连接)能够被许多人共享。 时间共享的天然对应物是空间共享,其中资源在但愿使用它的人之间被划分(在空间中)。 例如,磁盘空间天然是空间共享资源,由于一旦将块分配给文件,在用户删除它以前不可能将其分配给另外一个文件。学习

 

4.1 进程的抽象

运行的程序在操做系统中的抽象咱们称之为进程。如上所述,一个进程就是一个正在运行的程序。在任什么时候刻,咱们均可以经过对其在执行过程当中访问或影响的系统的不一样部分进行清点来总结一个过程。

为了理解流进程的构成,咱们必须了解其机器状态:程序在运行时能够读取或更新的内容。在任何给定时间,机器的哪些部分对执行该程序很重要?

包含进程的机器状态的一个明显组成部分是其存储器。指令存在内存中,运行程序读写的数据也在内存中。所以,进程能够寻址的内存(称为其地址空间)是进程的一部分。

进程的机器状态的一部分是寄存器。许多指令明确地读取或更新寄存器,所以它们对于执行过程很重要。

请注意,有一些特殊的寄存器构成了这种机器状态的一部分。例如,程序计数器(PC)(有时称为指令指针或IP)告诉咱们当前正在执行哪一个程序指令。相似地,堆栈指针和相关的帧指针用于管理函数参数,局部变量和返回地址的堆栈。

最后,程序一般也访问持久存储设备。此类I / O信息可能包括进程当前打开的文件列表。

 

提示:单独的政策和机制

在许多操做系统中,常见的设计范式是将高级策略与其低级机制分离[L + 75]。 您能够将机制视为提供有关系统问题的答案; 例如,操做系统如何执行上下文切换? 该政策为哪一个问题提供了答案; 例如,操做系统如今应该运行哪一个进程? 将二者分开能够很容易地改变策略,而没必要从新考虑该机制,所以是一种模块形式,通常的软件设计原则。

 

4.2 进程API

虽然咱们将实际流程API的讨论推迟到后续章节,但在这里咱们先了解一些操做系统的最基本的接口。这些API以某种形式可用于任何现代操做系统。

 

creat:一个操做系统必须包含一些建立新进程的方法。在shell中键入命令时,或双击应用程序图标,调用操做系统以建立一个新进程来运行您指定的程序。

destory因为存在用于建立流程的接口,所以系统还提供了强制销毁进程的接口。固然,许多进程都会运行完成后自行退出。可是,当他们不这样作时,用户可能但愿杀死他们,所以中止失控进程的接口很是有用。

wait:有时等待进程中止运行是有用的。所以常常提供某种等待接口。

Miscellaneous Control:除了杀死或等待进程以外,有时还有其余可能的控制。例如,大多数操做系统提供某种方法来暂停进程(阻止它运行一段时间)而后恢复它(继续运行)。

Status:一般还有接口来获取有关进程的状态信息,例如运行的时间或状态。

 

 

4.3 进程建立的一些细节

咱们应该揭露的一个谜团是一个程序是如何变成进程的?具体来讲,操做系统如何启动并运行程序?进程建立过程实际上如何运做?

操做系统运行程序必须作的第一件事是将其代码和任何静态数据(例如,初始化的变量)加载到进程的地址空间中。程序最初以某种可执行格式驻留在磁盘上(如今大都是基于闪存的SSD)。所以,将程序和静态数据加载到内存中的过程须要操做系统从磁盘读取这些字节并将它们放在内存中(如图4.1所示)。

在早期(或简单)操做系统中,加载过程是在运行程序以前完成的,即一次完成。现代操做系统懒惰地执行该过程,即,仅在程序执行期间须要加载代码或数据。要真正了解代码和数据的延迟加载是如何工做的,您必须更多地了解分页和交换的机制,咱们将在讨论内存虚拟化时讨论这些主题。如今,请记住,在运行任何操做以前,操做系统显然必须作一些工做才能将重要的程序位从磁盘放入内存。

 

一旦将代码和静态数据加载到内存中,操做系统在运行该进程以前还须要执行一些其余操做。必须为程序的运行时堆栈(或只是堆栈)分配一些内存。正如您可能已经知道的那样,C程序将堆栈用于存放局部变量,函数参数和返回地址。操做系统分配此内存并将其提供给进程。操做系统也可能会经过参数初始化堆栈。具体来讲就是,堆栈中会保存main()函数的参数,即argc和argv数组。

操做系统还能够为程序的堆建立一些初始内存。在C程序中,堆用于显式请求的动态分配数据。程序经过调用malloc()来请求这样的空间,并经过调用free()显式释放它。数据结构须要堆,例如链表,哈希表,树和其余有趣的数据结构。堆最初会很小;当程序运行,并经过malloc()库API请求更多内存时,操做系统可能会进入内核并为进程分配更多内存以帮助知足此类调用。操做系统还会执行一些其余初始化任务,尤为是与输入/输出(I / O)相关的任务。例如,在UNIX系统中,默认状况下每一个进程都有三个打开的​​文件描述符,用于标准输入,输出和错误。这些描述符使程序能够轻松地从终端读取输入以及将输出打印到屏幕。咱们将在本书的第三部分中详细介绍有关持久性的I / O,文件描述符等内容。

经过将代码和静态数据加载到内存中,经过建立和初始化堆栈,以及经过执行与I / O设置相关的其余工做,操做系统如今(最终)为程序执行设置了作好了铺垫。而后它还有一个最后的任务:跳转到在入口点去运行程序,即main()。经过跳转到main()例程(经过咱们将在下一章讨论的专用机制),OS将CPU的控制权转移到新建立的进程,从而程序开始执行。

 

4.4 进程状态

如今咱们已经知道一个进程是什么(虽然咱们将继续改进这个概念),而且(大体)知道如何建立它,让咱们谈谈一个过进程在给定时间能够处于的不一样状态。 在早期的计算机系统中出现了一个进程可能处于这些状态之一的概念。 在简化视图中,进程能够处于如下三种状态之一:

•正在运行(running):在运行状态下,进程正在处理器上运行。 这意味着它正在执行指令。

•就绪(ready):在就绪状态下,一个进程已准备好运行,但出于某种缘由,操做系统不选择在此时刻运行它。

•阻塞(blocked):在阻塞状态下,进程已执行某种操做,使其在其余事件发生以前没法继续运行。 一个常见示例:当进程向磁盘发起I / O请求时,它会被阻塞,而后其余一些进程可使用该处理器。

Figure 4.2: Process: State Transitions

若是咱们将这些状态映射到图表,咱们将到达图4.2中的图表。 正如您在图中看到的那样,能够根据操做系统的判断在准备状态和运行状态之间移动进程。 从准备运行到运行意味着该过程已被计划; 从运行转移到准备就绪意味着该过程已被取消预约。 一旦进程被阻塞(例如,经过启动I / O操做),OS将保持这样直到某些事件发生(例如,I / O完成); 此时,进程再次进入就绪状态(若是OS决定,可能会当即再次运行)。

 

4.5 数据结构

操做系统是一个程序,与任何程序同样,它有一些跟踪各类相关信息的关键数据构。例如,为了跟踪每一个进程的状态,操做系统可能会为全部准备好的进程保留某种进程表,以及跟踪当前正在运行的进程的一些附加信息。操做系统还必须以某种方式跟踪被阻止的进程。当I / O事件完成时,操做系统应确保唤醒正确的进程并准备好再次运行。

图4.3显示了操做系统须要跟踪xv6内核[CK + 08]中每一个进程的信息类型。相似的过程结构存在于“真实”操做系统中,例如Linux,Mac OS X或Windows。查看它们,看看它们有多复杂。

从图中,您能够看到操做系统跟踪流程的几个重要信息。对于已中止的进程,寄存器区域(PCB中的字段)将保持其寄存器的内容。当进程中止时,其寄存器将保存到该存储单元。经过恢复这些寄存器(即将它们的值放回实际的物理寄存器中),操做系统能够恢复运行该过程。咱们将在之后的章节中详细了解这种称为上下文切换的技术。

*Figure 4.3: The xv6 Proc Structure

您还能够从图中看到,除了运行,准备和阻塞以外,还有一些其余状态能够进入。 有时,系统中会有处于刚建立的初始状态的进程。 此外,能够将进程置于已退出但还没有清除的最终状态(在基于UNIX的系统中,这称为僵尸状态)。 这个最终状态可能颇有用,由于它容许其余进程(一般是建立进程的父进程)检查进程的返回代码,看看它是否已成功执行成功。(一般在基于UNIX的系统中,程序执行成功会返回零,不然非零)。 完成后,父进程将进行最后一次调用(例如,wait())以等待子进程完成,并向操做系统代表它能够清理任何涉及该进程的相关数据结构 - 灭绝过程。


 

ASIDE:数据结构 - 进程列表

操做系统充满了各类重要的数据结构,咱们将在这些对应的章节讨论。 进程列表是第一个这样的结构,并且是其中比较简单的一个。固然任何可以同时运行多个程序的操做系统都会有相似于这种结构的东西,以便跟踪系统中全部正在运行的程序。 有时人们会将存储过程信息的个体结构称为过程控制块(PCB),这是一种讨论包含每一个进程信息的C结构的奇特方式。


 

4.6 总结

咱们介绍了操做系统最基本的抽象:进程。 它被简单地视为一个正在运行的程序。 考虑到这一律念性观点,咱们如今将继续讨论实质性过程:实施进程所需的低层机制,以及以智能方式安排进程所需的更高层次的策略。 经过结合机制和策略,咱们将创建对操做系统如何虚拟化CPU的理解。

相关文章
相关标签/搜索