(5)进程(子进程的开启)

串行问题:

多道处理技术 (*******************)
1. 时间的复用,cpu在多个任务之间不断的进行切换

2. 空间的复用
多个任务必须开辟属于自己的内存空间 (物理级别的隔离)

相关概念:(*******************)
cpu: 计算执行任务的 不会执行IO操作(I/O输入/输出(Input/Output))

cpu切换的条件:
1. 遇到IO操作,就切换
2. 遇到优先级比较高的任务会进行切换
3. 如果某一个任务长时间占用CPU资源,也会切换 , 要所有的任务雨露均沾

什么是串行、并发以及并行

a. 串行 : 程序一个接一个的执行
b. 并发 : 单个CPU执行多个程序任务, CPU在程序之间不断的进行切换, 感觉好像是并行 (伪并行)
c. 并行 : 多个CPU同时执行多个程序任务

什么是进程
进程和程序的区别:
程序:静态的程序代码
进程:正在运行的程序

进程的开启方式(有两种方式)

开启进程需要调用multprocessing包下的Process

进程开启方式1,函数方式 (推荐这种方式,简单明了)
import time
from multiprocessing import Process #调用multprocessing包


def task(x):
print('%s is running' % x)
time.sleep(2)
print('%s is done' % x)


if __name__ == '__main__':
p = Process(target=task, args=('子进程',)) #开启进程需要实例化,开始进程实例
PS:实例化进程,需要执行的任务的目标函数就是task。当调用的时候就会将‘子进程’传给task函数的形参x
p.start() #向操作系统申请资源,开启子进程(包括子进程的空间大小,子进程的pid号,)
print('主...')

PS:Process里面的参数,traget就是执行任务的目标函数,args必须传入一个元祖(‘子进程’,),kwargs传一个字典{‘x’: '子进程'}就是传入的值(value)要赋值给哪一个变量(key)

PS:执行程序的时候,是从上而下运行的,所以在程序执行到开启子进程的时候(p.start),就是在主进程里开启了一个子进程,p.start这里就是向操作系统申请了一块内存空间,然后执行子进程的程序,但是申请的时间是慢于主进程,因为程序是一直由上而下的运行,不会停顿,开启子进程需要申请内存空间,这个动作是要向操作系统去申请,然后操作系统开辟一个内存空间给子进程,这一个过程是非常耗费资源和时间的,所以主进程的速度是快于子进程

进程开启方式2 类方式
from multiprocessing import Process
import time

class MyProcess(Process): #自己写一个类,但是这个类必须要继承Process类的

def __init__(self,x = None): #
super(MyProcess,self).__init__() #因为是继承Prcess类,所以要在Process类的基础上增加我们自己要的参数,要重写初始化函数
self.x = x #self.x是成员变量

def run(self): #子进程执行的这个函数不能乱写,必须要重写Process类下面的run
print('%s is running'%self.x)
print('%s is done' %self.x)

if __name__ == '__main__':
p = MyProcess('子进程') #这里实例化的是自己写的类
p.start()
print('主...')

子进程底层的运行原理

程序的运行的时候是由上而下运行,主进程是一个顺序的运行过程,在主进程运行的p.start()的时候,出现了一个分支运行了一个子进程,这时候主进程是不会停止的,继续向下运行,这时候子进程也是在运行,这个就叫做异步

主进程结束同时也会回收子进程

底层的运行原理

由于主进程(父进程)不知道子进程什么时候结束,所以主进程需要循环不断的向子进程发送一个wait/waitpd()函数,就是不断的向子进程询问状态(有没有执行完),收到子进程已经执行完的状态后,就会向操作系统发送请求,告诉操作系统所有的程序都已经执行完毕,这时候退出程序。

PS:所有的子进程在执行完毕之后并不会立即消失,操作系统会收回子进程占用的内存空间,但是会保留进程号,进程执行时间等,这个过程叫僵尸进程,所有的子进程都会经历一个过程叫僵尸进程,在僵尸进程时候就会告诉主进程已经执行完毕

进程的故障

1、主进程没结束,子进程还在运行,但是父进程不发送wait函数

主进程还在运行,主进程也不会向子进程循环发送一个wait/waitpd()函数,这时候主进程结束了,子进程继续在运行,如果操作系统里面主进程生成了大量的子进程,但是不回收,会导致系统奔溃死机,这时候用指令找到僵尸进程的父进程,直接杀死父进程,重启需要的进程即可

2、父进程结束,子进程继续运行(子进程就是孤儿进程)

孤儿进程会被一个权限最高的进程 init 进程接管,进程号(0),代替主进程的角色向子进程发送wait/waitpid()

原文地址:https://www.cnblogs.com/shizhengquan/p/10230093.html