- 进程间通信(IPC)
原因:进程空间相对独立,资源无法相互获取,此时在不同进程间通信需要专门方法。
进程间通信方法:管道 消息队列 共享内存 信号 信号量套接字
- 管道通信 Pipe
通信原理:在内存中开辟管道空间,生成管道操作对象,多个进程使用“同一个”管道对象进行操作即可实现通信
multiprocessing--》 Pipe
fd1,fd2 = Pipe(duplex = True)
功能:创建管道
参数:默认表示双向管道
设置False则为单向管道
返回值:表示管道的两端
如果是双向管道 都可以读写
如果是单向管道 则fd1只读 fd2只写
fd.recv()
功能:从管道读取信息
返回值:读取到的内容
* 如果管道为空则阻塞
fd.send(data)
功能:向管道写入内容
参数:要写入的内容
* 可以发送python数据类型,不用是byte格式
- 管道通信简单实现
#使用管道进行进程间的通信
from multiprocessing import Process,Pipe
import os,time
#创建管道对象,若是单向管道,fd2只写,fd1只读
fd1, fd2 = Pipe(False)
def fun(name):
time.sleep(3)
#向管道中写入内容
fd2.send('hello ' + str(name))
jobs = []
for i in range(5):
p = Process(target = fun,args = (i,))
jobs.append(p)
p.start()
for i in range(5):
#父进程读取管道
data = fd1.recv()
print(data)
for i in jobs:
i.join()
- 消息队列
通信原理:
在内存中简历队列数据结构模型,多个进程都可以通过队列存入内容,取出内容的顺序和存入顺序保持一致
创建队列
q = Queue(maxsize = 0)
功能:创建消息队列
参数:表示最多存放多少消息。默认表示根据内存分配存储
返回值:队列对象
q.put(data,[block,timeout])
功能:向队列存储消息
参数:data 要存的内容
block 默认队列满时会阻塞,设置为False则非阻塞
timeout 超时时间
q.get([block,timeout])
功能:获取队列消息
参数:block 默认队列空时会阻塞,设置为Faslse则非阻塞
timeout超时时间
返回值: 返回取出的内容
q.full() 判断队列是否为满
q.empty() 判断队列是否为空
q.qsize() 判断队列中的消息数量
q.close() 关闭队列
- 消息队列简单演示
#创建消息队列,实现进程间通信
from multiprocessing import Queue
from time import sleep
#创建队列
q = Queue(3)
q.put(1)
print(q.qsize())
print(q.full())
q.put(2)
print(q.qsize())
print(q.full())
q.put(3)
print(q.qsize())
print(q.full())
#q.put(4,True,3) 如果设置非阻塞,满后再加会报错
#若设置True,并添加超时时间,超过时间后仍然会报错
for _ in range(q.qsize()): print(q.get()) # 1 2 3
- 消息队列通信简单实现
#创建消息队列,实现进程间通信
from multiprocessing import Process,Queue
import time
#创建消息队列
q = Queue()
def fun1():
time.sleep(1)
q.put({'a':1,'b':2})
def fun2():
time.sleep(2)
print('收到消息:',q.get())
p1 = Process(target = fun1)
p2 = Process(target = fun2)
p1.start()
p2.start()
p1.join()
p2.join()
- 共享内存
通信原理:在内存中开辟一块空间,对多个进程可见,进程可以写入输入,但是每次写入的内容会覆盖之前的内容。
创建共享内存
obj = Value(ctype,obj)
功能:开辟共享内存空间
参数: ctype 要存储的数据类型
obj 共享内存的初始化数据
返回: 共享内存对象
obj.value 即为共享内存值,对其修改即修改共享内存
obj.Array(ctype,obj)
功能:开辟共享内存空间
参数: ctype 要存储的数据类型
obj 初始化存入的内容 比如列表,字符串
如果是整数则表示开辟空间的个数
返回值:返回共享内存对象
* 可以通过返回值遍历每个元素的值
[1,2,3] --> obj[1] == 2
* 如果存入的是字符串
obj.value 表示字符串的首地址
- 共享内存Value对象的通信实现
from multiprocessing import Process,Value
import time
import random
#创建共享内存
money = Value('i',2000)
#操作共享内存存钱
def deposite():
for i in range(100):
time.sleep(0.05)
#对value属性操作共享内存数据
money.value += random.randint(1,200)
#操作共享内存取钱
def withdraw():
for i in range(100):
time.sleep(0.04)
#对value属性操作共享内存数据
money.value -= random.randint(1,180)
d = Process(target = deposite)
w = Process(target = withdraw)
d.start()
w.start()
d.join()
w.join()
print('余额为',money.value)
- 共享内存Array对象的通信实现
#创建共享内存存入列表
from multiprocessing import Process,Array
import time
#创建共享内存,初始放入列表
#shm = Array('i',[1,2,3,4,5])
#创建共享内存,开辟5个整形空间
shm = Array('i',5)
def fun():
for i in shm:
print(i)
shm[3] = 199
p = Process(target = fun)
p.start()
p.join()
for i in shm:
print(i)

表中的Type code为Value方法的Ctype参数类型
- 三种通信方式对比
管道 消息队列 共享内存
开辟空间 内存 内存 内存
读写方式 两端读写 先进先出 覆盖之前内容
效率 一般 一般 较高
* 管道多用于父子进程
* 消息队列广泛灵活
* 共享内存需要注意进行互斥操作

3876

被折叠的 条评论
为什么被折叠?



