python3基础:多进程(一)

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础,进程是线程的容器。

基本概念

什么是进程?

进程的概念主要有两点:

第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令(比如错误信息打印的调用关系)和本地变量。

 

第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋

予程序生命时,它才能成为一个活动的实体,我们称其为进程。

进程的特征

  1. 动态性:进程的实质是程序在多任务系统中的一次执行过程,进程是动态产生,动态消亡的。
  2. 并发性:任何进程都可以同其他进程一起并发执行
  3. 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
  4. 异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度执行
  5. 结构特征:进程由程序、数据和进程控制块三部分组成。
  6. 多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。

进程切换

CPU由运算器,控制器和寄存器组成。运算器是对数据进行加工处理的部件,它不仅可以实现基本的算术运算,还可以进行基本的逻辑运算,实现逻辑判断的比较及数据传递,移位等操作;控制器是负责从存储器(内存和硬盘)中取出指令,确定指令类型及译码,按时间的先后顺序向其他部件发出控制信号,统一指挥和协调计算机各器件进行工作的部件;寄存器是CPU内部高速独立的暂时存储单元(容量很小)。CPU是按照时间片进行轮询对进程进行处理的。

进程切换就是从正在运行的进程中收回处理器,然后再使待运行进程来占用处理器。从某个进程收回处理器,实质上就是把进程存放在处理器寄存器中的中间数据存放在进程的私有堆栈,从而把处理器的寄存器腾出来让其他进程使用。让进程来占用处理器,实质上是把某个进程存放在私有堆栈中寄存器的数据(前一次本进程被中止时的中间数据)再恢复到处理器的寄存器中去,并把待运行进程的断点送入处理器的程序指针,于是待运行进程就开始被处理器运行了,也就是这个进程已经占有处理器的使用权了。

一个进程存储在处理器各寄存器中的中间数据叫做进程的上下文,分为用户级上下文/寄存器上下文/系统上下文。进程的切换实质上就是被中止运行进程与待运行进程上下文的切换。在进程未占用处理器时,进程的上下文是存储在进程的私有堆栈中的。

同步和异步/阻塞和非阻塞

同步:顺序执行

异步:不需要按顺序执行

有依赖关系时只能用同步,没有依赖关系可同步可异步

阻塞:正在运行的进程由于提出系统服务请求(如I/O操作),但因为某种原因未得到操作系统的立即响应,或者需要从其他合作进程获得的数据尚未到达等原因,该进程只能调用阻塞原语把自己阻塞,等待相应的事件出现后才被唤醒

非阻塞:无需等待

进程的五态模型

进程执行时的间断性,决定了进程可能具有多种状态,一般有以下5种状态:

  • 新建状态:

进程刚刚被创建时没有被提交的状态,并等待系统完成创建进程的所有必要信息。 进程正在创建过程中,还不能运行。操作系统在创建状态要进行的工作包括分配和建立进程控制块表项、建立资源表格(如打开文件表)并分配资源、加载程序并建立地址空间表等。创建进程时分为两个阶段,第一个阶段为一个新进程创建必要的管理信息,第二个阶段让该进程进入就绪状态。由于有了新建态,操作系统往往可以根据系统的性能和主存容量的限制推迟新建态进程的提交。

  • 就绪状态(Ready):

进程已获得除处理器外的所需资源,等待分配处理器资源;只要分配了处理器进程就可执行。就绪进程可以按多个优先级来划分队列。例如,当一个进程由于时间片用完而进入就绪状态时,排入低优先级队列;当进程由I/O操作完成而进入就绪状态时,排入高优先级队列。

  • 运行状态(Running):

进程占用处理器资源;处于此状态的进程的数目小于等于处理器的数目。在没有其他进程可以执行时(如所有进程都在阻塞状态),通常会自动执行系统的空闲进程。

  • 阻塞状态(Blocked):

由于进程等待某种条件(如I/O操作或进程同步),在条件满足之前无法继续执行。该事件发生前即使把处理机分配给该进程,也无法运行。注意:当I/O完成或者进程等待的事件发生后,进程进入就绪状态而不是运行状态,要等待CPU的轮询处理

  • 终止状态

进程已结束运行,回收除进程控制块之外的其他资源,并让其他进程从进程控制块中收集有关信息(如记帐和将退出代码传递给父进程)。类似的,进程的终止也可分为两个阶段,第一个阶段等待操作系统进行善后处理,第二个阶段释放主存。

 

​​​​​​​进程状态转换细分

由于进程的不断创建,系统资源特别是主存资源已不能满足所有进程运行的要求。这时,就必须将某些进程挂起,放到磁盘对换区,暂时不参加调度,以平衡系统负载,当条件允许的时候,会被操作系统再次调回内存,重新进入等待被执行的状态即就绪态;进程挂起的原因可能是系统故障,或者是用户调试程序,也可能是需要检查问题。

 

  1. 活跃就绪:是指进程在主存并且可被调度的状态。
  2. 静止就绪(挂起就绪):是指进程被对换到辅存时的就绪状态,是不能被直接调度的状态,只有当主存中没有活跃就绪态进程,或者是挂起就绪态进程具有更高的优先级,系统将把挂起就绪态进程调回主存并转换为活跃就绪。
  3. 活跃阻塞:是指进程已在主存,一旦等待的事件产生便进入活跃就绪状态。
  4. 静止阻塞:是指进程对换到辅存时的阻塞状态,一旦等待的事件产生便进入静止就绪。

注意:只要是挂起的进程,也就是静止就绪或者静止阻塞的进程都是方法磁盘中的,是不能被直接调度的。被激活后要先放入内存才能调度

​​​​​​​进程的创建过程

原语(原子操作):是由若干条指令组成的,用于完成一定功能的一个过程。具有不可分割性,即原语的执行必须是连续的,在执行过程中不允许被中断。

一旦操作系统发现了要求创建新进程的事件后,便调用进程创建原语Creat()按下述

步骤创建一个新进程。

1) 申请空白PCB(进程控制块):为新进程申请获得唯一的数字标识符,并从PCB集

合中索取一个空白PCB。

2) 为新进程分配资源:为新进程的程序和数据以及用户栈分配必要的内存空间。显然此时操作系统必须知道新进程所需要的内存大小。

3) 初始化进程控制块。PCB的初始化包括:

①初始化标识信息,将系统分配的标识符和父进程标识符,填入新的PCB中。

②初始化处理机状态信息,使程序计数器指向程序的入口地址,使栈指针指向栈顶。

③初始化处理机控制信息,将进程的状态设置为就绪状态或静止就绪状态,将它设置为最低优先级,除非用户以显式的方式提出高优先级要求。

将新进程插入就绪队列,如果进程就绪队列能够接纳新进程,便将新进程插入到就绪队列中。

​​​​​​​进程的终止过程

  • 引起进程终止的事件

1)正常结束

在任何计算机系统中,都应该有一个表示进程已经运行完成的指示。例如,在批处理系统中,通常在程序的最后安排一条Hold指令或终止的系统调用。当程序运行到Hold指令时,将产生一个中断,去通知操作系统本进程已经完成。

2)异常结束

在进程运行期间,由于出现某些错误和故障而迫使进程终止。这类异常事件很多常见的有:越界错误,保护错,非法指令,特权指令错,运行超时,等待超时,算术运算错,I/O故障。

3)外界干预

外界干预并非指在本进程运行中出现了异常事件,而是指进程应外界的请求而终止运行。这些干预有:操作员或操作系统干预,父进程请求,父进程终止。

  • 进程的终止过程

如果系统发生了上述要求终止进程的某事件后,OS便调用进程终止原语,按下述过程去终止指定的进程。

1)根据被终止进程的标识符,从PCB集合中检索出该进程的PCB,从中读出该进程状态。

2)若被终止进程正处于执行状态,应立即终止该进程的执行,并置调度标志为真,用于指示该进程被终止后应重新进行调度。

3)若该进程还有子孙进程,还应将其所有子孙进程予以终止,以防他们成为不可控的进程。

4)将被终止的进程所拥有的全部资源,或者归还给其父进程,或者归还给系统。

5)将被终止进程(它的PCB)从所在队列(或链表)中移出,等待其它程序来搜集信息。

​​​​​​​进程的阻塞过程/唤醒过程

  • 引起进程阻塞和唤醒的事件

1)请求系统服务

当正在执行的进程请求操作系统提供服务时,由于某种原因,操作系统并不立即满足该进程的要求时,该进程只能转变为阻塞状态来等待,一旦要求得到满足后,进程被唤醒。

2)启动某种操作

当进程启动某种操作后,如果该进程必须在该操作完成之后才能继续执行,则必须先使该进程阻塞,以等待该操作完成,该操作完成后,将该进程唤醒。

3)新数据尚未到达

对于相互合作的进程,如果其中一个进程需要先获得另一(合作)进程提供的数据才能运行以对数据进行处理,则是要其所需数据尚未到达,该进程只有(等待)阻塞,等到数据到达后,该进程被唤醒。

4)无新工作可做

系统往往设置一些具有某特定功能的系统进程,每当这种进程完成任务后,便把自己阻塞起来以等待新任务到来,新任务到达后,该进程被唤醒。

  • 进程阻塞过程

正在执行的进程,当发现上述某事件后,由于无法继续执行,于是进程便通过调用阻塞原语block把自己阻塞。进程的阻塞是进程自身的一种主动行为。进入block过程后,由于此时该进程还处于执行状态,所以应先立即停止执行,把进程控制块中的现行状态由执行改为阻塞,并将PCB插入阻塞队列。如果系统中设置了因不同事件而阻塞的多个阻塞队列,则应将本进程插入到具有相同事件的阻塞(等待)队列。最后,调度程序进行重新调度,将处理机分配给另一就绪进程,并进行切换。

  • 进程唤醒过程

当被阻塞的进程所期待的事件出现时,如I/O完成或者其所期待的数据已经到达,则由

有关进程(比如,用完并释放了该I/O设备的进程)调用唤醒原语wakeup,将等待该事件的进程唤醒。唤醒原语执行的过程是:首先把被阻塞的进程从等待该事件的阻塞队列中移出,将其PCB中的现行状态由阻塞改为就绪,然后再将该PCB插入到就绪队列中。

进程的调度算法

  • ​​​​​​​进程的调度算法包括:
  1. FIFO(First Input First Output 先进先出法)
  2. RR(时间片轮转算法)
  3. HPF(最高优先级算法)

python进程

  1. Python中一些进程模块:
  2. os.fork()(只能在linux中使用)
  3. subprocess
  4. processing
  5. Multiprocessing
  1. python中实现进程通信有以下几种方式:
  1. 文件
  2. 管道(Pipes)
  3. Socket
  4. 信号
  5. 信号量
  6. 共享内存

未完待续。。。

​​​​​​​参考:

https://www.cnblogs.com/xiawen/p/3328033.html

猜你喜欢

转载自blog.csdn.net/kongsuhongbaby/article/details/85108599