一、简介
进程间由于空间独立,资源无法互相直接获取,此时在不同的进程间进行数据传递就需要专门的通信方法。进程间通信的方法包含以下6种,本文将依次进行介绍:
二、管道通信Pipe
在内存中开辟一段内存空间、形成管道结构。管道对多个进程可见,进程可以对管道进行读写操作
from multiprocessing import Pipe
fd1,fd2=Pipe(duplex=True)
功能:创建一个管道
参数:默认为双向管道,如果设置为False,则为单向管道
返回值:对于双向管道fd1,fd2都可以进行读写操作;单相管道,fd1只可读,fd2只能写
读写操作:
fd.recv()–>从管道读取内容;返回值为读取的内容;如果管道无内容,则阻塞;
fd.send()–>向管道写入内容;参数为发送的内容;几乎可以发送所有Python支持的数据
三、消息队列
可以使⽤multiprocessing模块的Queue实现多进程之间的数据传递,Queue 本身是⼀个消息列队程序。
Queue.qsize(): 返回当前队列包含的消息数量;
Queue.empty(): 如果队列为空,返回True,反之False ;
Queue.full(): 如果队列满了,返回True,反之False;
Queue.get([block[, timeout]]):
获取队列中的⼀条消息,然后将其从列队中移除,block默认值为True;
Queue.get_nowait():
相当Queue.get(False);
Queue.put(item,[block[, timeout]]):
将item消息写⼊队列,block默认值 为True;
Queue.put_nowait(item):
相当Queue.put(item, False)
拓展: 请使用实例化对象的方式实现消息队列的通信方式.
四、信号
1、一个进程向另一个进程通过信号传递某种讯息,接收方在接收到信号后进行相应的处理;
【1】LINUX终端:
kill -l 查看信号名称和编号
` kill -signum PID 给PID的进程发送一个信号
(eg:kill -9 进程号 #杀死一个进程)
【2】程序执行的同步和异步
同步:按照步骤一步一步顺序执行
异步:在程序执行中利用内核,不影响应用层程序持续执行
信号是唯一的异步通信方式
【3】关于信号
信号名称:kill -l查看到的名称或编号
信号含义:信号的作用
默认行为:当一个进程接收到信号时采取的行为(终止进程,暂停进程,忽略产生)
e.g.
SIGHUP 终端断开
SIGINT ctrl + c
SIGQUIT ctrl + \
SIGTSTP ctrl + z
SIGKILL 终止进程且不能被处理
SIGSTOP 暂停进程且不能被处理
SIGALRM 时钟信号
SIGCHLD 子进程状态改变发给父进程
【4】通过Python进行信号处理:
os.kill(pid,sig)
功能:发送信号给某个进程
参数:pid 给哪个进程发送信号
sig:要发送什么信号
signal.alarm(sec)
功能:一定时间后给自身发送一个slgalrm信号
参数:指定时间
##一个进程只能设置一个时钟,第二个时钟会覆盖之前的时间
signal.pause()
功能:阻塞等待一个信号的发生
signal.signal(signum,handler)
功能:处理信号
参数: signum:要处理的信号
handler:信号处理的方法包含以下三种:
SIG_DFL 使用默认方法处理
SIG_IGN 忽略这个信号
func 自定义函数处理信号
def func(sig,frame):
“sig—表示要处理的信号;frame——信号的结构对象”
*signal函数是一个异步处理函数
*signal函数不能处理SIDSTOP信号
*在父进程中使用signal(SIGCHLD,SLG——IGN),这样子进程退出时会交给系统处理,是解决僵尸进程的惯用手法
五、共享内存
在内存中开辟一段空间,存储数据,对于多个进程可见。每次写入共享内存中的数据会覆盖之前的内容
【1】使用Value创建共享内存
obj =Value(ctype,obj)
功能:开辟共享内存空间
参数: ctype 字符串 要转变的c的数据类型
obj 共享内存的初始化数据
返回:共享内存对象
obj.value 表示共享内存中的值。对其修改或者使用即可
【2】使用Array创建共享内存
obj = Array(ctype,obj)
功能:开辟共享内存
参数:ctype 字符串 要转变的c的数据类型
obj 共享内存的初始化数据
1、列表:将列表存入共享内存,数据类型一致
2、正整数:表示开辟几个数据空间
六、信号量
给定一定的数量,对多个进程可见并且多个进程根据信号量的多少确定不同的行为(可用于操作共享的有限资源)
multiprocessing —> Semaphore()
sem = Semaphore(num)
功能:生成信号量对象
参数: 信号量的初始值
返回值: 信号量对象
sem.acquire() 信号量数量减1 信号量为0时会阻塞
sem.release() 信号量数量加1
sem.get_value() 获取当前信号量的值
七、本地套接字
linux进程间通信还可以使用socket本地套接字,socket函数的第一个参数设置为socket.AF_UNIX表示创建本地套接字;使用方法类似与socket网络编程。此处不在论述。
八、同步互斥机制
目的:解决对共有资源操作产生的争夺
临界资源:多个进程或者线程都能够操作的资源
临界区:操作临界资源的代码段
同步:是一种合作关系,为完成某个任务,多进程或多线程之间形成的一种协调。按照约定依次执行对临界资源的操作,相互告知相互促进。
互斥:互斥是一种制约关系,当一个进程占有临界资源就会进行加锁的操作,此时其他进程就无法操作该临界资源。直到使用的进程进行解锁操作后才能使用
Python中通过Event事件或Lock锁实现同步互斥机制:
1.Event
multiprocessing ---> Event
e = Event() #创建事件对象
e.wait([timeout]) #事件阻塞
e.set() #当e被set后,e.wait不再阻塞
e.clear() #当e被clear后,e.wait又会阻塞
e.is_set() #事件判断 判断当前事件对象是否被设置
2.Lock
multiprocessing ---> Lock
lock = Lock()
lock.acquire() #上锁
lock.release() #解锁
*上锁状态执行acquire()操作会阻塞
*解锁状态执行acquire()不阻塞
使用上下文管理器实现:
lock = multiprocessing.Lock()
with lock:--->上锁
...
--->with代码段结束即解锁