进程相关概念
程序与进程
程序是编译好的二进制文件,在磁盘上不占用系统资源(CPU、内存、打开的文件、设备、锁...)。进程是一个抽象的概念,与操作系统原理紧密相连。进程是活跃的程序,占用系统资源,在内存中执行。简单来说,程序运行起来就会产生一个进程。
程序与进程程序只是存在在磁盘中的文件,具体来说是由指令集与数据构成,被组织成为“正文段(指令集)+用户数据段(数据)”的形式。进程则是程序被加载到内存中并分配内存空间,存在着“正文段(指令集)+用户数据段(堆+栈)+ 系统数据段(PCB等系统用到的数据结构)”。简单来说,进程是由“正文段(text)”、“用户数据段(user segment)”、“系统数据段(system segment)”共同组成的一个执行环境。
进程的结构程序只是一个文件,也就是一个机器代码指令和数据的集合,这些指令和数据存储在磁盘上的一个可执行映像(Executable Image)中,所以程序是一个静态的实体。可执行映像是一个可执行文件的内容。简单来说,程序代表你期望完成某项工作的计划或步骤,等待具体实现,而具体的实现过程是由进程来完成的,进程可以认为是运行中的程序,除了包含程序中所有内容外,还包含额外的数据。
程序转载到内存后就可以运行了,在指令指针寄存器的控制下,不断地将指令取到CPU中进行运行,这些指令控制的对象不外乎各种存储器(内存、外存、CPU寄存器等),这些存储器中保存着待运行的指令和待处理的数据。当然,指令只有得到CPU才能发挥作用。可见,在计算机内部,程序的执行过程实际上是一个执行环境的综合。这个执行环境包括程序中各种指令和数据,还有一些额外数据,如寄存器的值、用来保存临时数据(如传递给函数的参数、函数的返回值、变量等)的堆栈(包括程序堆栈和系统堆栈)、被打开文件的数量、输入输出设备的状态等。这个执行环境的动态变化表征程序的运行,我们把这个环境称为进程,它代表程序的执行过程,是一个动态的实体,随着程序中指令的执行而不断地变化。在某个特定时刻进程的内容也被称为进程映像(Process Image)。
X86进程布局进程是一个动态的实体,进程实体由三部分组成:
- 正文段
text
正文段存放着被执行的机器指令,这个段是只读的,所以不能写自己能修改的代码,正文段允许系统中正在运行的两个或多个进程之间能够共享这一代码。例如,多个用户同时都在使用文本编辑器,在内存中仅需要改程序指令的一个副本,他们全都共享这一副本。
- 用户数据段
user segment
用户数据段存放进程执行时直接进行操作的所有数据,包括进程使用的全部变量在内。显然,这里包含的信息可以被修改。虽然进程之间可以共享正文段,但每个进程需要有自己的专用用户数据段。例如,同时编辑文本的多个 用户,虽然运行着同样的程序(编辑器),但每个用户都有着不同的数据(文本内容)。
- 系统数据段
system segment
系统数据段有效地存放程序运行的环境,事实上,这正是程序和进程的区别所在。系统数据段是进程实体最重要的一部分,之所以说它有效地存放程序运行的环境,是因为这部分存放着进程的控制信息。操作系统对不同的进程进行管理,是通过进程的控制信息来实现的。例如,Linux会为每个进程都建立一个task_struct
的数据结构来容纳进程的控制信息。
Linux是一个多任务操作系统,可以有多个程序同时转入内存并运行,操作系统为每个程序建立一个运行环境即创建进程,每个进程拥有自己的虚拟地址空间,它们之间互不干扰。即便要相互作用,也要通过内核提供的进程间通信机制(IPC)来完成。Linux内核支持多个进程虚拟地并发执行,这是通过不断地保存和切换程序的运行环境来实现的,选择哪个进程运行是由调度程序所决定的。注意有些地方会将进程切换(Process Switching)成为“环境切换”或“上下文切换”(Context Switching)。
进行运行过程中需要系统资源,例如,需要CPU来运行它的指令,需要使用系统的物理内存来容纳进程本身和它有关的数据,要在文件系统中打开和使用文件,并且可能直接或间接的使用系统的物理设备,如打印机、扫描仪等。由于这些系统资源是由所有进程所共享的,所以,Linux必须监视进程和它所拥有的系统资源,使它们可以公平地拥有系统资源以得到运行。
并发
并发在操作系统中是指一个时间段中有多个进程都处于已启动运行到运行完毕之间的状态,但任一时刻点上仍然只会有一个进程在运行。
并发 时钟中断机制并发是指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得宏观上具有多个进程同时执行的效果,但微观上并不是同时执行的,只是把时间切分为若个段,使多个进程快速交替执行。
单道程序设计
所有进程一个一个排队执行,若A阻塞则B只能等待,即使CPU处于空闲状态。而在人机交互时阻塞的出现是必然的。所有这种模型在系统资源利用上极不合理,在计算机发展历史上存在不久便被淘汰了。
多道程序设计
多道程序设计是指允许多个程序同时进入一个计算机系统的主存储器并启动进行计算的方式,引入多道程序设计的根本目的是提高CPU的利用率,充分发挥系统部件的并行性。采用多道程序设计方法后,提高了效率即增长了单位时间的计算量,但对于每一道程序来说,却延长了计算时间。所以,多道程序设计技术提高资源利用率和系统吞吐率是以牺牲用户的响应时间为代价的。
多道程序设计在计算机内存中同时存在多道相互独立的程序,它们在管理程序控制之下,相互穿插运行。多道程序设计必须有硬件基础作为保证。
时钟中断是多道程序设计模型的理论基础,并发时任意进程在执行期间都不希望放弃CPU,因此系统需要有一种强制让进程让出CPU资源的手段,时钟中断由于具有硬件基础作为保障,对进程而言是不可抗拒的。一般在操作系统中,使用中断处理函数来负责调度程序的执行。在多道程序设计模型中,多个进程轮流使用CPU(分时复用CPU资源),而当下的CPU都是纳秒级,即1秒可以执行大约10亿条指令,由于人眼的反应速度是毫秒级别的,所以看似是同时在运行。实际上,并发是宏观上的并行微观上的串行。
多道程序设计的出现,加快了操作系统的诞生。
CPU和MMU
MMU(Memory Manage Unit)内存管理单元是一个与软件密切相关的硬件部件,它是CPU用来管理虚拟内存和物理内存的控制线路,同时也负责将虚拟地址映射为物理地址,并提供硬件机制的内存访问授权。
CPU和MMU早期DOS系统阶段,计算机内存都是以K为单位进行计算,容量非常小。相应的程序规模也不太。但随着图形界面的兴起和用户需求的增加,应用程序的规模随之不断膨胀。出现了应用程序太大以至于内存容纳不下的问题,通常的解决方案是将程序分割为许多称为覆盖块(overlay)的片段,覆盖块0首先运行,结束时将调用另一个覆盖块。虽然覆盖块的交换是由操作系统来完成过的,但必须先由程序员把程序先进行分割,这是一个费时费力的工作而且相当枯燥。不久人们找到了更好的方法,就是虚拟存储器(virtual memory),它的思想是程序、数据、堆栈总的大小可以超过硬件存储器的大小,操作系统把当前使用的部分保留在内存中,而把其他未被使用的部分保留在磁盘上。在需要时在内存和磁盘之间交换程序片段。