一、进程间通信
进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。
由于每个进程的空间是互相独立的,进程之间无法互相直接获取彼此的资源,故引入进程间通信来实现进程间的资源交互。
进程间通信方法:管道、消息队列、共享内存、信号、信号量、套接字。
补充:文件类型(查看方法:ls -l 或 ll)
b(块设备文件)
c(字符设备文件)
d(文件夹)
- (普通文件)
l (链接文件) link
s 套接字文件
p 管道文件
二、管道通信 Pipe
在内存中开辟一段空间,形成管道结构,管道对多个进程可见,进程可以对管道进行读写操作,实现多进程之间的通信。
from multiprocess import Pipe # 导入库
1、Pipe函数
fd1,fd2 = Pipe(duplex = True)
功能:创建一个管道
参数:默认为双向管道
如果设置为False,则为单向管道
返回值:返回两个管道流对象,表示管道的两端
如果双向管道,fd1 fd2都可以进行读写操作
如果是单向管道,则fd1只可读,fd2只可写
fd.recv()
功能:从管道读取内容(接收消息)
参数:无
返回值:读到的内容(接收消息)
说明:如果管道无内容则阻塞
功能: 向管道写入内容(发送消息)
参数: 要发送的内容
说明:如果没有接收端则管道破裂
2、示例
from multiprocessing import Process,Pipe
import os,time
#如果参数为False则fd1只能recv fd2只能send
# fd1,fd2 = Pipe(False)
#创建一个双向管道
fd1,fd2 = Pipe()
# fd1.close()
def fun(name):
time.sleep(3)
#发字符串到管道
fd2.send("hello " + str(name))
print(os.getppid(),"----",os.getpid())
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()
三、消息队列 Queue
队列存取规则: 先进先出
在内存中开辟队列结构空间,多个进程可以向队列投放消息,在取出的时候按照存入顺序取出;任何拥有队列的进程都可以存取消息
1、Queue函数
创建队列
q = Queue(maxsize = 0)
功能 : 创建队列
参数 : maxsize 默认为0,表示根据系统分配空间存储消息
如果传入一个正整数,表示最多存放多少条消息
返回 : 消息队列对象
q.put(data, [block, timeout])
功能: 存放消息
参数: data 存入的消息 (python数据类型)
block 默认为True表示当队列满的时候阻塞
设置为False则表示非阻塞
timeout 当block为True表示超时时间
data = q.get([block, timeout])
功能 : 取出消息
参数 : block 默认为True 当队列空时阻塞
设置为False表示非阻塞
timeout 当block为True时表示超时时间
返回值 : 返回获取的消息
q.full() 判断队列是否为满
q.empty() 判断队列是否为空
q.qsize() 判断当前队列有多少消息
q.close() 关闭队列
2、示例
a、函数
from multiprocessing import Queue
from time import sleep
#创建队列
q = Queue(3)
q.put(1)
print(q.full())
q.put(2)
q.put(3)
print(q.full())
# 设置超时事件为3sec
# q.put(4,True,3)
print(q.get())
print("队列中还有%d条消息"%q.qsize())
print(q.empty())
q.close() #关闭队列
b、管道收发
from multiprocessing import Process,Queue
import time
#创建消息队列
q = Queue()
def fun1():
time.sleep(1)
q.put("我是进程1")
def fun2():
time.sleep(2)
print("取消息:",q.get())
p1 = Process(target = fun1)
p2 = Process(target = fun2)
p1.start()
p2.start()
p1.join()
p2.join()
四、共享内存
在内存中开辟一段空间,存储数据,对多个进程可见。每次写入共享内存中的数据会覆盖之前的内容。由于对内存格式化较少,所以存取速度快。
from multiprocessing import Value,Array
1、函数
obj = Value(ctype,obj)
功能:开辟共享内存空间
参数:ctype 字符串 要转变的c的数据类型(对照ctype表)
obj 共享内存的初始化数据
返回:返回一个共享内存对象
补充:obj.value 表示共享内存中的值。对其修改或者使用即可
obj = Array(ctype,obj)
功能: 开辟共享内存
参数: ctype 要转化的c的类型
obj 列表,表示要存入的数据,要求列表中数类型一致
正整数,表示开辟一个多大的序列空间
返回值:返回一个共享内存对象
补充:正常操作数值,读取和赋值
2、数据类型(ctype对照表)
Type code | C Type | Python Type | Minimum size in bytes | Notes |
---|---|---|---|---|
'b' | signed char | int | 1 | |
'B' | unsigned char | int | 1 | |
'u' | Py_UNICODE | Unicode character | 2 | (1) |
'h' | signed short | int | 2 | |
'H' | unsigned short | int | 2 | |
'i' | signed int | int | 2 | |
'I' | unsigned int | int | 2 | |
'l' | signed long | int | 4 | |
'L' | unsigned long | int | 4 | |
'q' | signed long long | int | 8 | (2) |
'Q' | unsigned long long | int | 8 | (2) |
'f' | float | float | 4 | |
'd' | double | float | 8 |
3、示例
a、共享内存 —— value
from multiprocessing import Value,Process
import time
import random
#向共享内存存钱
def deposite(money):
for i in range(100):
time.sleep(0.03)
money.value += random.randint(1,200)
#从共享内存取钱
def withdraw(money):
for i in range(100):
time.sleep(0.02)
money.value -= random.randint(1,150)
#创建共享内存对象
money = Value('i',2000)
d = Process(target = deposite,args = (money,))
w = Process(target = withdraw,args = (money,))
d.start()
w.start()
d.join()
w.join()
#查看共享内存数据
print(money.value)
b、共享内存 —— array
from multiprocessing import Array,Process
import time
def fun(shm):
for i in shm:
print(i)
shm[2] = 1000
#开辟共享内存空间,可容纳6个整数
#初始值是[1,2,3,4,5,6]
# shm = Array('i',[1,2,3,4,5,6])
#表示在共享内存中开辟一个包含6个整形的空间
shm = Array('i',6)
p = Process(target = fun,args = (shm,))
p.start()
p.join()
for i in shm:
print(i)