进程(二)
***************************Day05********************************
一、(进程)写一个简单的群聊聊天室
1、功能 : 类似qq群聊
1. 进入聊天室需要输入姓名,姓名不能重复
2. 有人进入聊天室会向其他人发送通知
xxx 进入了聊天室
3. 一个人发消息,其他人会收到消息
xxx 说 : xxxxxxxx
4. 某人退出聊天室,其他人也会收到通知
xxx 退出了聊天室
5.管理员喊话:服务端发送消息所有的客户端都就收到
管理员说:xxxxx
功能模型:转发
需要的技术:套接字通信 udp套接字
用户存储:字典或列表
消息收发的随意性:多进程
2、代码设计:
1、封装 将每个功能封装为函数
2、接口测试(每实现一步就测试一步)
3、代码编写流程
搭建网络连接 --》创建多进程 --》 每个进程功能编写 --》 项目功能模块实现
4、进入聊天室
客户端:输入姓名 将信息发给服务端(L name)
等待服务端回复 根据回复判断是否登录成功
服务端:接收请求信息 判断请求类型 判断用户名是否存在
如果存在回复不能登录 如果不存在回复可以登录并插入到数据结构
发送通知给其他用户
5、聊天
客户端:创建父子进程 发送聊天请求/接受聊天信息
服务端:接受请求信息 讲消息转发给其他客户端
6、退出聊天
客户端 : 发送消息退出 Q name
接受回复
退出程序
服务端 : 接受消息
判断请求类型
从用户结构删除对应用户
告知所有人,xxx退出
7、管理员消息
二、multiprocessing 模块创建进程
1. 需要将要做的事情封装成函数
2. 使用multiprocessing模块中提供的类Process创建进程对象
3. 通过进程对象属性设置和Process初始化进程进行进程的设置,绑定要执行的函数
4. 启动进程,会自动执行进程绑定的函数
5. 完成进程的回收
三、创建进程对象:Process()
功能:创建进程对象
参数:name: 给进程起的名称 (默认Process-1)
target:要绑定的函数
args: 元组,给target函数按照位置传参
kwargs: 字典,给target函数按照键值对传参
四、启动进程与回收子进程
1、p.start()
功能 : 启动进程
* terget函数会自动执行,此时进程真正被创建。
2、p.join([timeout])
功能: 阻塞等待回收子进程(子进程退出)
参数: 超时时间
* 使用multiprocessing创建子进程,同样子进程复制父进程的全部代码段(内存空间),父子进程各自执行互不影响,父子进程有各自的运行空间
* 如果不使用join回收子进程,则子进程退出后会成为僵尸进程
* 使用multiprocessing创建子进程,往往父进程只是用来创建进程回收进程(功能就是创建子进程回收子进程,所有事件交给子进程完成)
* 子进程也是有自己特有的PID等资源
注意:
1、如果子进程从父进程拷贝对象,对象和网络或者文件相关联,那么父子进程会使用同一套对象属性,互相有一定关联性
2、如果在子进程中单独创建对象,则和父进程完全没有关联
cookie:
获取文件大小
size = os.path.getsize("./timg.jpeg")
总结:
1. 如何处理僵尸进程
* 通过wait waitpid
* 通过创建二级子进程,让一级子进程退出
2. multiprocessing创建进程
* Process 类 创建进程对象
* 通过start启动进程
* 通过join回收子进程
****************************Day06*****************************
一、Process进程对象属性
p.start() 启动进程
p.join() 阻塞等待回收子进程(子进程退出)
p.is_alive() 判断进程生命周期(alive)状态,处于生命周期得到True,否则返回False
p.name 进程名称 默认为Process-1
p.pid : 创建的新的进程的PID号
p.daemon
认状态为False 主进程退出不会影响子进程执行
如果设置为True 则子进程会随着主进程结束而结束
* daemon 属性设置要在start() 前
* 设置daemon为True,则一般不需要加join(一般不和join一起使用)
二、创建自定义进程类
1、编写类继承Process
2、编写自己的__init__,同时加载父类init方法
(即在自定义类中加载父类__init__以获取父类属性,同时可以自定义新的属性)
3、重写run方法,可以通过生成的对象调用start自动执行该方法
三、多进程优缺点
优点:可以使用计算机多核,进行任务的并发执行,提高执行效率
空间独立,数据安全
运行不受其他进程影响,创建方便
缺点:进程的创建和删除消耗的系统资源较多
四、进程池技术
1、产生原因:
如果有大量任务需要多进程完成,则可能需要频繁的创建删除进程,给计算机带来较多的资源消耗。
2、原理:
创建适当的进程放入进程池,用来处理待处理事件。处理完毕后进程不销毁,仍然在进程池中等待处理其他事件。进程的复用降低了资源的消耗
3、使用方法:
1、创建进程池,在池内放入适当的进程
2、将事件加入到进程池等待队列
3、不断取进程执行事件,直到所有事件执行完毕
4、关闭进程池,回收进程
4、from multipeocessing import Pool
1、Pool(processrs)
功能:创建进程池对象
参数:表示进程池有多少进程数量
返回:进程池对象
2、pool.apply_async(func,args,kwds)
功能:将事件放入进程池队列执行
参数:fun 要执行的事件函数
args 以元组形式给func传参
kwds 以字典形式给func传参
返回值:返回一个进程池事件的对象(通过get()属性函数可以获取fun的返回值)
3、pool.close()
功能: 关闭进程池,无法再加入事件
4、pool.join()
功能: 回收进程池
5、pool.map(func,iter)
功能:将要执行的事件放入到进程池
参数:func 要执行的函数
iter 迭代对象,给func传参
返回值:返回事件函数func的返回值列表
五、进程间通信(IPC)
原因:进程空间相对独立,资源无法相互获取,此时在不同进程间通信需要专门方法。
进程间通信方法:管道 消息队列 共享内存 信号 信号量 套接字
1、管道通信 Pipe
1、通信原理:在内存中开辟管道空间,生成管道操作对象,多个进程使用“同一个”管道对象进行操作即可实现通信。
2、multiprocessing ---》 Pipe
fd1,fd2 = Pipe(duplex = True)
功能: 创建管道
参数:默认True表示双向管道,如果设置为False则为单向管道
返回值:两个管道对象fd1、fd2,分别表示管道的两端
如果是双向管道则均可以读写;如果是单向管道则fd1只读,fd2只写。
3、fd.recv()
功能:从管道读取信息
返回值:读取到的内容
* 当管道为空则阻塞
4、fd.send(data)
功能: 向管道写入内容
参数:要写入的内容
* 管道满时会阻塞
* 可以发送python数据类型(几乎所有的)
2、消息队列
1、队列:先进先出
2、通信原理:在内存中建立队列数据结构模型。多个进程都可以通过队列存入内容,取出内容的顺序和存入顺序保持一致。
3、创建队列
q = Queue(maxsize = 0)
功能:创建队列对象
参数:maxsize 默认表示系统自动分配队列空间
如果传入正整数则表示最多存放多少条消息。
返回值 : 队列对象
4、q.put(data,[block,timeout])
功能:向队列中存入消息
参数:data 要存的消息内容(支持python数据类型)
block 默认True表示队列满时会阻塞,设置为False则为非阻塞
timeout 超时时间(单位秒)
5、data = q.get([block,timeout])
功能: 获取队列消息
参数:block 默认为True表示队列空时阻塞,设置为False则为非阻塞
timeout 超时时间
返回值:返回获取到的消息内容
6、q.full() 判断队列是否为满
7、q.empty() 判断队列是否为空
8、q.qsize() 判断队列中消息数量
9、q.close() 关闭队列
3、共享内存
1、通信原理:在内存中开辟一块空间,对多个进程可见,进程可以写入输入,但是每次写入的内容会覆盖之前的内容。
2、from multiprocessing import Value,Array
obj = Value(ctype,obj)
功能:开辟共享内存空间
参数:ctype 要存储的数据类型(字符串,要转变的c的类型)
obj 共享内存的初始化数据
返回:共享内存对象
3、obj.value 即为共享内存中的值,对其修改即修改共享内存
4、obj = Array(ctype,obj)
功能: 开辟共享内存空间
参数: ctype 要存储的数据格式
obj 要存入共享内存的数据内容,如:列表、字符串 表示要存入的内容,要求类型相同
* 如果是整数则表示要开辟空间的个数
返回值: 返回共享内存对象(可迭代对象)
* 可以通过遍历过户每个元素的值
e.g. [1,2,3] ---> obj[1] == 2
* 如果存入的是字符串
obj.value 表示字符串的首地址
总结:
管道 消息队列 共享内存
开辟空间 内存 内存 内存
读写方式 两端读写 先进先出 每次覆盖上次内容
双向/单向
效率 一般 一般 较快
应用 多用于父子进程 应用灵活广泛 需要注意进行同步互斥操作(复杂)
4、信号通信
1、通信原理:一个进程向另一个进程发送一个信号来传递某种讯息,接受者根据接收到的信号进行相应的行为
2、kill -l: 查看信号方式
3、kill -sig PID: 向一个进程发送信号(sig(为1-64))
4、关于信号
信号名称 信号含义 默认处理方法
SIGHUP 连接断开 终止
SIGINT CTRU-C发出 终止
SIGQUIT CTRU-\ 终止
SIGTSTP CTRL-Z 暂停
SIGKILL 终止一个进程(且不能被阻塞、处理或忽略)
SIGSTOP 暂停一个进程(且不能被阻塞、处理或忽略)
SIGALRM 时钟信号 终止
SIGCHLD 子进程状态改变时给父进程发出 忽略
5、Python发送信号
signal
os.kill(pig,sig)
功能:发送信号
参数:pid 目标进程PID号
sig 要发送的信号
6、信号通信方法
1、import signal
signal.alarm(sec)
功能: 向自身发送时钟信号 --》SIGALRM
参数: sec 时钟时间(秒)
* 一个进程中只能有一个时钟,后来的时候会覆盖前面的时间
2、程序的同步执行和异步执行:
同步执行:程序按照步骤一步一步执行,呈现一个先后性和顺序性
异步执行:在执行过程中利用内核记录延迟发生或者准备处理的事件,这样不影响应用层的持续执行。当事件发生时再由内核告知应用层处理
* 信号是唯一的异步通信方法
3、signal.pause()
功能: 阻塞进程等待接收一个信号
4、signal.signal(signum,handler)
功能:处理信号
参数:signum 要处理的信号
handler 信号的处理方法
可选值:SIG_DFL 表示使用默认的方法处理
SIG_IGN 表示忽略这个信号
func 传入一个函数表示用指定函数处理(自定义函数)
自定义函数格式:def func(sig,frame)
sig: 捕获(接收)到的信号
frame:信号结构对象
* signal函数也是一个异步处理函数。只要执行了该函数,则进程任意时候接收到相应信号都会处理。
* signal 是不能处理 SIGKILL SIGSTOP的
* 父进程中可以用 signal(SIGCHLD,SIG_IGN)将子进程的退出交给系统处理
* 信号是一种异步的进程间通信方法
总结:
1. 进程对象属性
p.pid p.name p.is_alive() p.daemon
2. 自定义进程类
继承Process 重写run
3. 进程池 大量进程事件需要频繁创建删除进程
Pool() apply_async() close() join() map()
4.进程间通信
管道 消息队列 共享内存 信号 信号量 套接字
管道: Pipe() fd.recv() fd.send()
消息队列: Queue() q.get() q.put() q.full()
q.empty() q.qsize() q.close()
共享内存: Value() Array()
信号 : kill -l
kill -sig PID
kill(pid,sig)
****************************Day07*****************************
一、信号量(信号灯)
原理:给定一定的数量,对多个进程可见,并且多个进程都可以操作,进程通过对信号数量多少的判断执行各自的行为。
multiprocessing --》Semaphore
1、sem = Semaphore(num)
功能 : 创建信号量对象
参数 : 信号量的初始值
返回 : 信号量对象
2、sem.get_value() 获取当前信号量的值
3、sem.acquire() 将信号量数量减1,当数量为0则阻塞
4、sem.release() 将信号量数量加1
二、进程的同步互斥
1、临界资源:多个进程或者线程都能够操作的共享资源
2、临界区:操作临界资源的代码段
3、同步:同步是一种合作关系,为完成某个任务,多进程或者多线程之间形成一种协调,按照约定或条件执行操作临界资源。
4、互斥:互斥是一种制约关系,当一个进程或者线程使用临界资源时进行上锁处理,当另一个进程使用时会阻塞等待,直到解锁后才能继续使用。
三、Event 事件
multiprocessing --》 Event
1、创建事件对象
e = Event()
2、设置事件阻塞
e.wait([timeout])
功能:使进程处于阻塞状态,直到事件对象被set
参数:timeout 为超时时间
3、事件设置(当事件被设置后e.wait()不再阻塞)
e.set()
功能 : 让事件对象变为被设置状态
4、清除设置(当事件设置被clear后 e.wait又会阻塞)
e.clear()
功能 : 使事件对象清除设置状态
5、事件状态判断
e.is_set()
功能:判断当前事件对象的状态
四、Lock 锁
multiprocessing --》 Lock()
1、创建对象
lock = Lock()
2、上锁:lock.acquire()
* 如果一个锁对象已经被上锁(处于上锁状态)则再调用acquire会阻塞
3、解锁:lock.release()
4、with lock: 等同于lock.acquire() 上锁
语句块
....
* 语句块执行完自动解锁
总结:
1. 信号处理 signal()
* 异步通信方式 ---》 同步执行 异步执行
2. 信号量 Semaphore()
acquire() 删除
release() 增加
get_value() 获取
3. 同步互斥机制 :
解决了多个进程或者线程对共享资源的争夺
Event e.set e.clear e.wait
Lock lock.acquire() lock.release()
posted on 2018-10-12 15:35 破天荒的谎言、谈敷衍 阅读(311) 评论(0) 收藏 举报
浙公网安备 33010602011771号