快乐Linux —— 9. 进程模型剖析
参考:
《从哲学层次上看操作系统》
《深入理解计算机系统》
《操作系统精髓与设计原理》
https://blog.csdn.net/qq_38410730/article/details/81415419 进程与文件
简述
计算机发展早期,为了提高 CPU 的利用率,人们想起将多个程序同时加载到计算机里,并发执行。这些同时存在于计算机内存的程序就成为进程,其就是为了提高 CPU 利用率而出现的概念。
进程(process)其经典定义是 一个执行中程序的实例。 当我们在系统上运行一个程序时,我们会感到仿佛我们的进程是独占处理器和内存,这种假象就是操作系统通过进程的概念提供的。
我们可以说,一个进程是由程序代码、相关数据、进程控制块组成的。
我们重点关注进程提供给应用程序的两个关键抽象的实现:
- 一个私有的地址空间,它使我们觉得仿佛我们的程序使独占内存。进程的空间
- 一个独立的逻辑控制流,它使我们觉得仿佛我们的程序使独占 CPU。进程的时间
地址空间
在一个 n 位地址地机器上,地址空间是 2^n 个地址的集合。一般而言,一个进程所占用的物理内存是不能被其它进程访问的。从这一点讲地址空间是私有的。
尽管每个私有地址空间的内容是不同的,但它们一般都具有相同的结构。下图是一个32位 Linux进程的地址空间的组织结构。
进程的管理
操作系统为了管理进程和资源,必须掌握每个进程和资源的当前状态,普遍采用的方法是,操作系统构造并维护其管理的每个实体的信息表。基本上有以下几种:内存表,I/O表,文件表,进程表,这些也是操作系统重要职责,我们此时主要关心进程表。
这里我们需要注意的是:这些表是相互引用的。一个进程要和内存 I/O 文件打交道的话,就需要对这些资源直接或间接的引用。
由上面我们可知,一个实际的模型中有以下几部分
其中进程控制块中的信息主要分为三类:进程标识信息,处理器状态信息,进程控制信息。
进程的上下文
进程是在操作系统支持下执行的,进程执行时需要操作系统为其设置相应的执行环境,如系统堆栈、地址映像寄存器、程序计数器、程序状态字、打开文件表以及相关通用寄存器等。 所以,把进程的物理实体与支持进程执行的物理环境合称为进程上下文。
进程的位置
一个进程的位置取决于操作系统所采用的内存管理方案,在最简单的情形下,整个进程在连续的物理内存上。不过主流情况下,我们采用虚拟内存并采用页映射的方式将进程装载到内存上,在这种情况下,进程被分为一页一页,部分页在内存上,部分页在磁盘上,并且在内存上的页之间不一定连续,并且任何没有顺序关系。
这里的顺序关系 举个例子,如果把物理内存比作多层抽屉,把杯子比作进程的话,杯子被分为杯盖和杯身,把杯子放到抽屉上,不一定杯盖就在杯身所在抽屉的上面的抽屉。
操作系统的执行
如果操作系统仅是像其他程序那样由处理器执行的一组程序,那么操作系统是一个进程吗?如果是,如何控制它?这些有趣的问题使得人们提出了大量的设计方法。简单的说有下面三种方式:
其中我们常用的是第二种,这种方法也是较小计算机(PC、工作站)的操作系统通常采用的方法。
在这种方法下,操作系统代码和数据位于共享地址空间中,并被所有用户进程共享。在用户进程的上下文中执行所有操作系统功能。根据用户模式和内核模式的概念,即使操作系统例程在用户进程环境内执行,用户也不能篡改或干涉操作系统例程。
当发生中断、陷阱或系统调用时,处理器置于内核模式,保存模式上下文并切换模式(模式切换),再切换到一个操作系统例程,但此时仍然是在当前的用户进程内继续执行,不需要切换进程,只是在同一进程中切换模式。当操作系统完成操作后,需要继续运行当前的进程,则会切换模式在当前进程内恢复已中断的程序。
当进程在内核模式下运行时,有单独的内核栈用于管理调用/返回。
有时,会保存一个进程的状态信息,从就绪态进程中选择另一个进程,并把控制权交给这个新进程。涉及到进程状态变化,所以需要上下文切换。
进程与文件
- fs 存储进程对应的程序的文件在文件系统的位置。
- files 指向进程打开的文件表。
- 当fork 之后 两个进程的 files 会指向同一个files_struct 。
逻辑控制流
在一个进程的执行过程中,我们可以通过单步调试,看到程序计数器( Program Counter)的值,这些值唯一地对应于可执行目标文件或运行时动态连接到程序的共享对象中的指令。这个 PC 的值的序列就称为逻辑控制流,又简称(逻辑流)。
并发并行流
- 当多个逻辑流逻辑上执行时间重叠,其中每个流称为并发流(concurrent flow),这些流并发地运行。例如上图的 A 和 B ,A 和 C 在某段时间并发地运行,而 B 和 C 没有。
- 当多个逻辑流物理上执行时间重叠,称每个流为并行流(parallel flow),当两个流并发地运行在不同 CPU 上那么它们称为并行流。并行是并发地真子集,条件比并发更严格。例如上图 只有 A 与 C在一段时间内并行地运行。
进程的状态
一个进程有多种状态,不同的系统的实现不同,一个经典的模型是三种状态:执行态,就绪态,阻塞态。
这里阐述的进程三状态并不是唯一的分类方式。事实上,许多商业操作系统的进程状态不止三个,例如,Windows的进程有7个,Solaris里面的进程则有6个。但不管3个6个7个还是几个,其目的都是便于操作系统对进程的管理。只要细分对管理有利,我们就细分。否则就维持三状态。
进程的切换
进程切换(上下文切换):
- 保存处理器的上下文,包括程序计数器和其他寄存器。
- 更新当前处于运行态进程的进程控制块,包括改变进程的状态。还须更新其他相关的字段,包括退出运行态的原因和记账信息。
- 把该进程的进程控制块移到相应的队列(就绪、阻塞、就绪/挂起)。
- 选择另一个进程执行。
- 更新所选进程的进程控制块,包括把进程的状态改为运行态。
- 更新内存管理数据结构。是否需要更新取决于管理地址转换的方式。
- 载入程序计数器和其他寄存器先前的值,将处理器的上下文恢复为所选进程上次退出运行态时的上下文。
模式切换:处理器状态(模式)从用户态到核心态或者从核心态到用户态的转换。一般有以下步骤:
- 将程序计数器置为中断处理程序的开始地址。
- 从用户模式切换到内核模式,以便中断处理代码包含特权指令。
这个过程需要保存的上下文主要是PCB 中的处理器状态信息。模式切换不同于进程切换,它不一定会引起进程状态的转换,在大多数情况下,也不一定引起进程切换。可以看出涉及状态变化的进程切换与模式切换相比要做的工作更多。
进程相关的其它信息
创建一个进程
当创建一个新进程时,操作系统会执行以下操作:
-
为新进程分配一个唯一的进程标识符
主进程表会添加一个新表项。
-
为进程分配空间
包括进程模型中的所有元素。若任何已有的地址空间将被这个新进程共享,则要建立正确的链接。
-
初始化进程控制块
初始化进程标识信息,处理器状态信息,进程控制信息。进程最初不拥有任何资源(IO设备、文件),除非显式地请求了这些资源或继承了父进程的资源。
-
加入调度队列
例如,若操作系统将每个调度队列都维护为一个链表,则新进程必须放在就绪或就绪/挂起链表中。
-
创建或扩充其他数据结构。
例如,操作系统可因编制账单或评估性能,为每个进程维护个记账文件。
后续学习过程中如果有新的疑问再进行补充。。。