├── IPC ├── msg_queue.py ├── pipe-1-single_duplex.py ├── pipe-2-half-duplex.py ├── pipe-3-named.py ├── semaphore.py └── shareMemory.py └── README.md /IPC/msg_queue.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2019/4/8 17:54 3 | # @Author : ELI 4 | # @IDE : PyCharm 5 | # @PJ_NAME : Queue 6 | 7 | 8 | from multiprocessing import Process 9 | from multiprocessing import Queue 10 | from time import sleep 11 | 12 | def write(q): 13 | for i in range(5): 14 | # sleep(1) 15 | print('put %s to queue..' % i) 16 | q.put(i) 17 | 18 | 19 | def read(q): 20 | while 1: 21 | sleep(0.5) 22 | v = q.get(True) 23 | print('get %s from queue..' % v) 24 | 25 | 26 | if __name__ == '__main__': 27 | q = Queue() 28 | p1 = Process(target=write, args=(q,)) 29 | p2 = Process(target=read, args=(q,)) 30 | p1.start() 31 | p2.start() 32 | p1.join() # 等待p1进程跑完后再往下执行 33 | 34 | while not q.empty():# 队列不为空时阻塞在这 35 | sleep(1) 36 | 37 | p2.terminate() # 结束p2进程 38 | -------------------------------------------------------------------------------- /IPC/pipe-1-single_duplex.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2019/4/8 11:38 3 | # @Author : ELI 4 | # @IDE : PyCharm 5 | # @PJ_NAME : pipe-2 6 | 7 | ''' 8 | #标准库提供的管道是普通管道,单工的,读写方向固定 9 | 特点:只允许具有亲缘关系的两个进程通信 10 | ''' 11 | import os, sys 12 | 13 | print("The child will write text to a pipe and ") 14 | print("the parent will read the text written by child...") 15 | 16 | # file descriptors r, w for reading and writing 17 | r, w = os.pipe() 18 | 19 | processid = os.fork() #fork 方法仅能在linux系统上运行,跨平台就用multiprocess 20 | 21 | print(processid) 22 | 23 | if processid: 24 | # This is the paunameent process 25 | # Closes file descriptor w 26 | os.close(w) 27 | r = os.fdopen(r) 28 | print("Parent reading") 29 | str = r.read() 30 | print("text =", str) 31 | sys.exit(0) 32 | else: 33 | # This is the child process 34 | os.close(r) 35 | w = os.fdopen(w, 'w') 36 | print("Child writing") 37 | w.write("Text written by child...") 38 | w.close() 39 | print("Child closing") 40 | sys.exit(0) -------------------------------------------------------------------------------- /IPC/pipe-2-half-duplex.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2019/4/4 15:07 3 | # @Author : ELI 4 | # @IDE : PyCharm 5 | # @PJ_NAME : __init__.py 6 | 7 | ''' 8 | 使用多进程中的管道,它是半双工的,读写方向不固定 9 | 特点:只允许具有亲缘关系的两个进程通信 10 | ''' 11 | # 参考 http://www.cnblogs.com/konglinqingfeng/p/9696484.html 12 | from multiprocessing import Pipe, Process 13 | 14 | def func(conn1,conn2): 15 | conn2.close() #子进程只需使用connection1,故关闭connection2 16 | while True: 17 | try: 18 | msg = conn1.recv() #无数据则阻塞 19 | print(msg) 20 | except EOFError: #对端关闭后,就无法继续接收了 21 | print(1111) 22 | conn1.close() 23 | break 24 | 25 | if __name__ == '__main__': 26 | conn1,conn2 = Pipe()#建立一个管道,管道返回两个connection, 27 | p = Process(target=func, args=(conn1,conn2)) 28 | p.daemon = True #子进程必须和主进程一同退出,防止僵尸进程 29 | p.start() 30 | 31 | conn1.close() #主进程只需要一个connection,故关闭一个 32 | for i in range(20): 33 | conn2.send('吃了吗') #主进程发送 34 | conn2.close() #主进程关闭connection2 35 | 36 | -------------------------------------------------------------------------------- /IPC/pipe-3-named.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2019/4/8 15:35 3 | # @Author : ELI 4 | # @IDE : PyCharm 5 | # @PJ_NAME : pipe-3 6 | 7 | # 参考https://www.cnblogs.com/shijingjing07/p/7899611.html 8 | ''' 9 | 使用FIFO(命名管道)来实现任意两个进程间的通信 10 | 特点: 11 | 1. 和无名管道一样,半双工 12 | 2. 每个FIFO管道都与一个路径名相关联,类似一个文件 13 | 3. 进程间通过读写FIFO来通信 14 | 15 | **注意:这种方式对子进程的生命周期管理并不方便,不建议在python中使用** 16 | ''' 17 | import os, time 18 | pipe_name = 'pipe_test' 19 | 20 | def child(): 21 | #子进程负责写 22 | pipeout = os.open(pipe_name, os.O_WRONLY) # 必须以只写模式 23 | counter = 0 24 | while counter < 10: #不要写死循环,控制不好就是僵尸进程 25 | print('write Number %03d\n' % counter) 26 | os.write(pipeout, b'Number %03d\n' % counter) #这里是非阻塞的 27 | counter +=1 28 | time.sleep(1) 29 | 30 | def parent(): 31 | #父进程负责读 32 | # pipein = open(pipe_name, 'r') #也可以用内置函数open,和操作文件一样 33 | fd = os.open(pipe_name, os.O_RDONLY) # 必须以只读模式,获取一个file descriptor 34 | #fd是一个非负整数,只在单个进程中有意义,单个进程中一个fd对应一个待操作文件。 35 | while True: 36 | # line = pipein.readlines()[:-1] 37 | line = os.read(fd, 20) # 每次读20个字节,读出后FIFO管道中会马上清除数据 38 | #open和os.read都是非阻塞的 39 | if line: 40 | print('Parent %d got "%s" at %s' % (os.getpid(), line, time.time())) 41 | else: 42 | print('Parent %d no data'% os.getpid()) 43 | time.sleep(1) 44 | 45 | if not os.path.exists(pipe_name): 46 | os.mkfifo(pipe_name) #创建FIFO管道 47 | 48 | pid = os.fork() #创建子进程 49 | if pid: 50 | parent() 51 | else: 52 | child() 53 | 54 | ''' 55 | 这种模式允许多个进程(>=2)间通信 56 | ''' -------------------------------------------------------------------------------- /IPC/semaphore.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2019/4/8 17:47 3 | # @Author : ELI 4 | # @IDE : PyCharm 5 | # @PJ_NAME : semaphore 6 | 7 | ''' 8 | 9 | 进程间通信之---信号量 10 | 特点:不传输数据,用于多进程的同步 11 | 参考: https://blog.csdn.net/sinat_27864123/article/details/78490164 12 | ''' 13 | 14 | import multiprocessing 15 | import time 16 | 17 | def consumer(s): 18 | s.acquire() #信号量的使用与互斥量类似 19 | print(multiprocessing.current_process().name+' 正在执行') 20 | time.sleep(2) #执行时会发现同一时刻只有2个进程在执行 21 | s.release() 22 | print(multiprocessing.current_process().name+' release') 23 | 24 | 25 | if __name__ == '__main__': 26 | s = multiprocessing.Semaphore(5) #把信号量值设置为2,一次提供给两个消费者服务 27 | for i in range(5): #启5个进程 28 | p = multiprocessing.Process(target=consumer,args=(s,)) 29 | p.daemon = True #跟随主进程死亡,如果生产环境使用,最好加上这个,否则主进程结束时,子进程还在运行的话,就会造成孤儿进程(内存泄露) 30 | p.start() 31 | 32 | time.sleep(3) #等一下子进程 33 | print('main end') 34 | -------------------------------------------------------------------------------- /IPC/shareMemory.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2019/4/8 17:58 3 | # @Author : ELI 4 | # @IDE : PyCharm 5 | # @PJ_NAME : shareMemory 6 | 7 | 8 | ''' 9 | 进程间通信之---共享内存 10 | 特点: 11 | 1. 最快的IPC方式 12 | 2. 因为多个进程可以同时操作,所以需要进行同步 13 | 3. 可通过与信号量或锁结合使用实现多个进程间同步 14 | 共享方案: 15 | a. 消息队列 16 | b. 文件映射(为了在进程间共享内存,内核专门留有一个内存区,主进程将需要共享的数据映射到这块内存中,其他进程访问这个共享内存) 17 | ''' 18 | 19 | from multiprocessing import Process,Queue,Semaphore,current_process 20 | from time import sleep 21 | my_semaphore = Semaphore(2) 22 | 23 | ''' 24 | 错误的示例! 25 | ''' 26 | global_list = list(range(5)) #进程间不共享内存,所以每个进程访问的是这个对象的副本,并不是同一个对象 27 | 28 | def change_global_list(global_list,s): 29 | s.acquire() 30 | print('process_id:%s before change'% current_process().name, global_list) 31 | global_list.pop() 32 | sleep(1) 33 | s.release() 34 | print('process_id:%s after change'% current_process().name,global_list) 35 | 36 | 37 | if __name__ == '__main__': 38 | from multiprocessing import Manager, freeze_support 39 | manager = Manager() 40 | print(dir(manager))#'address', 'connect', 'dict', 'get_server', 'join', 'list', 'register', 'shutdown', 'start' 41 | global_list = manager.list() 42 | 43 | global_list.extend(list(range(5))) 44 | 45 | for i in range(5): 46 | p = Process(target=change_global_list,args=(global_list,my_semaphore)) 47 | p.daemon = True 48 | p.start() 49 | 50 | sleep(3) # 等一下子进程 51 | print('over!') 52 | 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IPC-Inter-Process-Communication 2 | 3 | ### Code implemention for Inter-Process Communication By Python3.6 4 | ### 六种进程间通信方式的Python3.6代码实现 5 | 6 | * 1. msg_queue (消息队列) 7 | * 2. pipeline for single duplex (单工管道) 8 | * 3. pipeline for half duplex (半双工管道) 9 | * 4. name pipeline (命名管道) 10 | * 5. share memory (共享内存) 11 | * 6. semaphore (信号量) 12 | --------------------------------------------------------------------------------