进程:
程序在计算机中的一次执行过程, 进程是一个动态的过程,占有计算机资源,有一定的生命周期
* 同一个程序不同的运行过程是不同的进程。因为分配的资源和生命周期都不相同
进程的创建流程
1. 用户启动一个程序或者调用接口发起进程创建
2. 操作系统接收用户请求分配计算机资源创建进程
3. 操作系统将一定状态的进程提供给用户使用
4. 用户利用操作系统提供的进程完成任务
进程相关概念
cpu时间片
如果一个进程占有cpu此时我们称为该进程占有cpu时间片。多个进程任务会轮流占有cpu时间片形成并发效果。
进程信息 (process)
PCB (进程控制块):进程创建后会自动在内存生产一个空间存放进程信息。
进程信息 : 进程的ID 进程占有内存的位置,创建时间,创建用户。。。
查看系统该进程信息 : ps -aux
PID(process ID) : 在操作系统中每个进程都有唯一的PID值是由系统分配的。
进程特征
* 进程是操作系统分配资源的最小单元
* 每个进程拥有自己独立的运行空间 (虚拟内存空间)
* 进程之间运行相互独立互不影响
进程的状态
三态
* 就绪态 : 进程具备执行条件,等待系统分配处理器 资源进入运行态
* 运行态 : 进程占有cpu处于运行状态
* 等待态 : 进程暂时不具备运行条件,需要阻塞等待
五态 (三态基础上增加新建和终止)
* 新建 : 创建一个新的进程,获取系统资源的过程
* 终止 : 进程执行结束,释放资源的过程
ps -aux ---> STAT表示进程状态
D 等待态 阻塞 不可中断等待态
S 等待态 睡眠 可中断等待态
T 等待态 暂停 暂停执行
R 运行态(就绪态)
Z 僵尸
+ 前台进程 (在终端运行)
< 有较高优先级的进程
N 较低优先级的进程
s 会话组
l 有进程连接
进程的优先级
top 动态查看进程优先级
< > 进行翻页 q退出
优先级的取值范围 : -20 --- 19 -20最高
nice : 以指定的优先级运行一个程序
nice -9 ./while.py 以9的优先级运行
sudo nice --9 ./while.py 以-9优先级运行
cookie
首行添加
#!/usr/bin/python3
修改程序权限添加可执行权限
chmod 775 while.py
可以直接指明路径执行
./while.py
父子进程
在系统中除了初始化进程每个进程都有一个父进程,可能有0个或多个子进程。由此形成进程间的父子关系。
便于进程管理,父进程发起创建子进程请求
查看进程树: pstree
查看父子进程PID : ps -ajx
要求:
1.什么是进程,进程和程序的区别
2.了解进程的特征和基本概念
3.理解并发并行的区别
4.清楚进程的状态及转换
os.fork 创建进程
pid = os.fork()
功能 : 创建进程
返回值:失败返回一个负数
成功 : 在原有进程中返回新进程的PID号
在新进程中返回0
* 子进程会复制父进程全部内存空间包括代码段
* 子进程会从fork的下一句开始执行
* 父进程中fork返回值即为新创建子进程的PID号
* 父子进程不一定谁先执行,执行上互不干扰抢占时间片
* 使用if 语句结构使父子进程执行不同的代码几乎是fork 创建进程的固定结构
* 在子进程中对变量等其他内容的修改,不会影响父进程中 的内容
* 子进程虽然复制父进程内容,但是也有自己的特有属性特征。比如: PID号 PCB 内存区间等
获取进程PID
os.getpid()
功能:获取进程的PID号
返回值 : 返回进程的PID号
os.getppid()
功能:获取父进程的PID号
返回值 : 返回父进程的PID号
进程退出
os._exit(status)
功能 : 退出一个进程
参数 : 进程的退出状态 整数
sys.exit([status])
功能 : 退出一个进程
参数 : 默认为0
如果传入一个整数则同 _exit()
传入一个字符串。则在对出时打印该字符串
* sys.exit() 可以通过捕获 SystemExit异常阻止退出
multiprocessing 模块创建进程
1. 需要将要做的事情封装成函数
2. 使用multiprocessing提供的类Process创建进程对象
3. 通过进程对象和Process初始化进程进行进程的设置,绑 定函数
4. 启动进程,会自动执行绑定的函数
5. 完成进程的回收
创建进程对象
Process()
功能: 创建进程对象
参数: target : 要绑定的函数
name : 给进程起的名称 (默认Process-1)
args: 元组 用来给target函数位置传参
kwargs : 字典 用来给target函数键值传参
p.start()
功能 : 启动进程 自动运行terget绑定函数。此时进程被 创建
p.join([timeout])
功能: 阻塞等待子进程退出
参数: 超时时间
* 使用multiprocessing创建进程子进程同样复制父进程的全部内存空间,之后有自己独立的空间,执行上互不干扰
* 子进程也是有自己特有的PID等资源
* 如果不使用join回收可能会产生僵尸进程
* 使用multiprocessing创建子进程,一般父进程功能就是创建子进程回收子进程,所有事件交给子进程完成
Process(target,name,args,kwargs)
name : 给进程起名字
默认为Process-1 Process-2.....
p.name 可以获取进程名称
args : 以元组的形式给target函数传参
kwargs : 以字典的形式给对应键的形参传参
进程对象的其他属性方法
p.name p.start() p.join()
p.pid : 创建的新的进程的PID号
p.is_alive() 判断进程是否处于alive状态
p.daemon 默认为False 如果设置为True 则主进程退出时子 进程也会结束
* daemon 属性设置要在start() 前
* 设置daemon为True 则一般不需要加join
cookie
获取文件大小
size = os.path.getsize("./timg.jpeg")
注意:
如果多个子进程拷贝同一个父进程中的对象,则多个子进程使用的是同一个对象(如文件对象,套接字,队列,管道。。。)
如果是在创建子进程后单独创建的对象,则多个子进程各不相同
创建自定义进程类
1. 编写类继承Process
2. 在自定义类中加载父类__init__以获取父类属性,同时可以自定义新的属性
3. 重写run方法,在调用start时自动执行该方法
进程的缺点
进程在创建和销毁的过程中消耗的资源相对较多
进程池技术
产生原因 : 如果有大量的任务需要多进程完成,而任务周期又比较短且需要频繁创建。此时可能产生大量进程频繁创建销毁的情况,消耗计算机资源较大
使用方法 :
1. 创建进程池,在池内放入适当数量的进程
2. 将事件封装函数,放入到进程池
3. 事件不断运行,知道所有放入进程池事件运行完成
4. 关闭进程池,回收进程
from multiprocessing import Pool
Pool(processes)
功能:创建进程池对象
参数:进程数量
返回 : 进程池对象
pool.apply_async(fun,args,kwds)
功能 : 将事件放入进程池执行
参数: fun 要执行的事件函数
args 以元组为fun传参
kwds 以字典为fun传参
返回值 : 返回一个事件对象 通过get()属性函数可以获取
fun的返回值
pool.apply(fun,args,kwds)
功能 : 将事件放入进程池执行
参数: fun 要执行的事件函数
args 以元组为fun传参
kwds 以字典为fun传参
pool.close()
功能: 关闭进程池,无法再加入事件
pool.join()
功能 : 回收进程池
pool.map(func,iter)
功能 : 将要执行的事件放入到进程池
参数 : func 要执行的函数
iter 迭代对象,给func传参
返回值 : 返回 func的返回值列表
进程间通信(IPC)
由于进程间空间独立,资源无法共享,此时在进程间通信就需要专门的通信方法。
进程间通信方法 : 管道 消息队列 共享内存 信号
信号量 套接字
管道通信
在内存中开辟一块空间,形成管道结构,多个进程使用同一个管道,即可通过对管道的读写操作进行通信
multiprocessing ---》 Pipe
fd1,fd2 = Pipe(duplex = True)
功能: 创建管道
参数:默认表示双向管道
如果设置为False则为单向管道
返回值 : 两个管道对象,分别表示管道的两端
如果是双向管道则均可读写
如果是单向管道则fd1只读 fd2只写
fd.recv()
功能:从管道读取信息
返回值 :读取到的内容
* 当管道为空则阻塞
fd.send(data)
功能: 向管道写入内容
参数: 要写入的内容
* 管道满时会阻塞
* 可以写入几乎所有的python数据
消息队列
队列 : 先进先出
在内存中开辟队列结构空间,对多个进程可见。多个进程操作同一个队列对象可以实现消息的存取工作。