在讨论操作系统时,总是出现的一个问题涉及如何调用所有CPU活动。早期的计算机是执行作业jobs的批处理系统,随后出现了运行用户程序user programs任务tasks的分时系统。即使在单用户系统上,用户也可以一次运行多个程序:文字处理器,Web浏览器和电子邮件包。而且即使计算机一次只能执行一个程序,例如在不支持多任务的嵌入式设备上,操作系统也可能需要支持其自己的内部编程活动,例如内存管理。在许多方面,所有这些活动都是相似的,因此我们将他们都称为进程processes

尽管我们个人更喜欢更具现代意义的术语processes,但是术语jobs具有历史意义,因为许多操作系统理论和术语实在在操作系统的大多数行为都是job处理的那个年代,发展而来的。因此,在某些适当的情况下,我们在描述操作系统角色时会使用job。例如,仅由于process已取代job,而避免使用包含单词job(例如工job scheduling)一词的普遍接受的术语会产生误导。

进程

非正式的,如前所述,进程是正在执行的程序。进程的当前活动的状态由程序计数器的值和处理器寄存器的内容表示。进程的内存布局通常分为多个部分,如下图所示。这些部分包括:

操作系统2.1进程的概念特征和状态(操作系统-进程的概念)(1)

进程的内存布局

请注意,文本数据部分的大小固定的,因为它们的大小在程序运行时不会改变。但是,栈和堆部分可以在程序执行期间动态收缩和增长。每次调用函数时,包含函数参数,局部变量和返回地址的激活记录activation recoed将被压入栈;当从函数返回控件时,激活记录将从栈中弹出。同样,堆将随着内存的动态分配而增长,并在将内存返回给系统时缩小。尽管栈和堆部分彼此接近toward,但是操作系统必须确保它们不会相互重叠overlap

我们需要强调的是,程序本身不是进程。程序是一个被动passive实体,例如包含磁盘上存储的指令列表的文件(通常称为可执行文件executable file)。相反,进程是活动active实体,程序计数器指定要执行的下一条指令以及一组关联的资源。当将可执行文件加载到内存中时,程序成为一个进程。加载可执行文件的两种常用技术是双击代表可执行文件的图标,和在命令行上输入可执行文件的名称(如prog.exe或a.out)然后回车。

尽管两个进程可能与同一程序相关联,但仍将它们视为两个单独的执行序列。例如,几个用户可能正在运行邮件程序的不同副本,或者同一用户可能调用Web浏览器程序的许多副本。这些都是独立的进程。尽管文本部分是等效的,但数据,堆和堆栈部分却有所不同。产生一个在运行时会产生许多进程的进程也是很常见的。

这里需要注意的是,进程本身可以是其他代码的执行环境。 Java编程环境提供了一个很好的例子。在大多数情况下,可执行Java程序在Java虚拟机(JVM)中执行。 JVM作为解释加载的Java代码并代表该代码执行操作(通过本机指令)的进程执行。例如,要运行已编译的Java程序Program.class,我们将输入

java Program

java命令将JVM作为普通进程运行,该进程又在虚拟机中执行Java程序Program。除了使用Java语言编写代码而不是使用其他指令集编写,这个概念与仿真类似。

操作系统2.1进程的概念特征和状态(操作系统-进程的概念)(2)

操作系统2.1进程的概念特征和状态(操作系统-进程的概念)(3)

进程状态

进程执行时,它会更改状态。进程的状态由该进程的当前活动定义。进程可能处于以下状态之一:

这些名字是任意的,在不同的操作系统里他们有着不同的名字。然而,它们代表的状态却是在所有的系统中都可以找到的。某些操作系统还可以更好地描述进程状态。重要的是要意识到在任何时刻任何处理器core上都只能运行一个进程。然而,其他许多进程可能已经ready并且waiting。与这些状态相对应的状态如下图所示。

操作系统2.1进程的概念特征和状态(操作系统-进程的概念)(4)

进程控制块

在操作系统里的每个进程都由一个进程控制块Process control block(PCB)所代表。一个PCB如下图所示,

操作系统2.1进程的概念特征和状态(操作系统-进程的概念)(5)

它包含了关于指定进程许多信息:

简而言之,PCB就是充当开始或重新启动进程所需的所有数据以及一些账户数据的存储库。

线程

到目前为止讨论的进程模型已经暗示了进程是执行单个线程的程序。例如,当进程正在运行文字处理器程序时,指令的单个线程正在执行。这种单一的控制线程使进程一次只能执行一个任务。因此,用户无法同时键入字符并运行拼写检查器。大多数现代操作系统都扩展了进程概念,以使进程具有多个执行线程,从而可以执行一次完成多个任务。在多线程可以并行运行的多核系统上,此功能特别有用。例如,多线程文字处理器可以分配一个线程来管理用户输入,而另一个线程运行拼写检查器。在支持线程的系统上,PCB被扩展为包括每个线程的信息。为了支持线程,还需要对整个系统进行其他更改。

,