-
进程间通信(IPC)
原因:进程空间相对独立,资源无法相互获取,此时在不同的进程间通信需要专门的方法
进程间通信方法: 管道 ,消息队列 ,共享内存, 信号, 信号量, 套接字
管道通信(Pipe)
通信原理:在内存中开辟管道空间生成管道操作对象,多个进程使用'同一个'管道对象进行操作,即可实现通信
multiprocessing --->Pipe
fd1,fd2 = Pipe(duplex = True)
功能:创建管道
参数:默认表示双向管道
如果设置为False则为单项管道
返回值: 表示管道的两端
如果是双向管道都可以读写
如果是单项管道 则fd1只读 fd2只写
fd.recv()
功能:从管道读取信息
返回值:读取到的内容没有参数
*如果管道内容为空则阻塞
fd.send(data)
功能:向管道写入内容
参数: 要写入的内容
*可以发送python数据类型
# pipe.py
from multiprocessing import Process, Pipe
import os, time
# 创建管道对象
fd1, fd2 = Pipe()
def fun(name):
time.sleep(3)
# 向管道写入内容
fd2.send(123456)
jobs = []
for i in range(4):
p = Process(target = fun, args = (i,))
jobs.append(p)
p.start()
for i in range(4):
# 读取管道
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])
功能:获取队列信息
参数:data要存的内容
block 默认队列空时会阻塞,设置为False则非阻塞
timeout 超时时间
返回值:返回取出的内容
q.full() :判断队列是否为满
q.empty():判断队列是否为空
q.qsize():判断队列中消息数量
q.close():关闭队列
# queue2.py
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()
# 收到消息: {'a': 1, 'b': 2}
共享内存
通信原理:在内存中开辟一块空间,对多个进程可见,进程可以写入输出,但是每次写入的内容会覆盖之前的内容
obj = Value(ctype,obj)
功能:开辟共享内存空间
参数:ctype 要存储的数据类型
obj 共享内存的初始化数据
返回:共享内存对象
obj.value 即为共享内存值,对其修改即修改共享内存
obj = Array(ctype, obj)
功能:开辟共享内存空间
参数:ctype 要存储的数据格式
obj 初始化存入的内容 比如:列表, 字符串
如果是数字则表示开辟空间的个数
返回值:返回共享内存对象
*可以通过遍历获取每一个元素的值
eg. [1,2,3]---->obj[1] == 2
*如果存入的是字符串
obj.value 表示字符串的首地址
管道 消息队列 共享内存
开辟空间 内存 内存 内存
读写方式 两端读写 先进先出 覆盖之前内容
双向/单向
效率 一般 一般 较高
应用 多用于父进程 广泛灵活 需要注意
进行互斥操作
# value.py
from multiprocessing import Process, Value
import time
import random
# 创建共享内容
money = Value('i', 2000)
# 操作共享内存增加
def deposite():
for i in range(100):
time.sleep(0.005)
# 对value属性操作即操作共享内存数据
money.value += random.randint(1, 200)
# 取钱
def withdraw():
for i in range(100):
time.sleep(0.04)
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)
信号通信
一个进程向另一个进程发送一个信号来传递某种讯息,接受者根据接受到的某种信号进行相应的行为
kill -l 查看系统信号
kill -sig PID 向一个进程发送信号
关于信号
信号名称 信号含义 默认处理方法
SIGHUP 连接断开
SIGINT CTRL-C
SIGQUIT CTRL-Z
SIGSTP 终止一个进程
SIGKILL 暂停一个进程
SIGALRM 时钟信号
SIGCHLD 子进程状态改变时给父进程发出
python 发送信号
signa1
os.kill(pid, sig)
功能:发送信号
参数: pid 目标进程
sig 要发送的信号
# signal_1.py
from signal import *
import time
def handler(sig,frame):
if sig == SIGALRM:
print('接收到时钟信号')
elif sig == SIGINT:
print('就不结束')
alarm(5)
signal(SIGALRM, handler)
signal(SIGINT, handler)
while True:
print('waiting for a signal')
time.sleep(2)
# waiting for a signal
# waiting for a signal
# waiting for a signal
# 接收到时钟信号
# waiting for a signal
# waiting for a signal
# waiting for a signal
# waiting for a signal
# ^C就不结束
# waiting for a signal
# ^C就不结束
# ^C就不结束
# waiting for a signal
# ^\退出 (核心已转储)
# kill.py
import os
import signal
# 向51405 发送信号
os.kill(51405, signal.SIGKILL)
信号的使用
import signal
signal.alarm(sec)
功能: 向自身发送时钟信号-->SIGALRM
参数: sec 时钟时间
*进程中只能有一个时钟,第二个会覆盖第一个时间
同步执行:按照顺续逐步执行,一步完成再做下一步
异步执行:在执行过程中利用内核记录延迟繁盛或者准备处理的事件,这样不影响应用层的持续 执行.当事件发生时,再由内核告知应用层处理
*信号是唯一的异步通信方法
signal.pause()
功能:阻塞等待接受一个信号
signal.signal(signum, handler)
功能:处理信号
参数:signum 要处理的信号
handler 信号的处理方法
SIG_DFL 表示使用默认的方法处理
SIG_IGN 表示忽略这个信号
func 传入一个函数表示用指定函数处理
def func(sig, frame)
sig:捕获到的信号
frame:信号的对象