• [并发编程] 进程间通信


    1.进程间通信方式

    套接字、信号、匿名管道、命名管道、共享内存和全局对象、队列和子类

    2.管道

    管道是Linux由Unix那里继承过来的进程间的通信机制,它是Unix早期的一个重要通信机制。

    其思想是,在内存中创建一个共享文件,从而使通信双方利用这个共享文件来传递信息。

    由于这种方式具有单向传递数据的特点,所以这个作为传递消息的共享文件就叫做“管道”。

    3.匿名管道

    概览

    由父进程创建的子进程将会赋值父进程包括文件在内的一些资源。如果父进程创建子进程之前创建了一个文件,那么这个文件的描述符就会被父进程在随后所创建的子进程所共享。

    也就是说,父、子进程可以通过这个文件进行通信。

    如果通信的双方一方只能进行读操作,而另一方只能进行写操作,那么这个文件就是一个只能单方向传送消息的管道。如下图所示:

    基本操作

    '''
    1.子进程通过os.write -> 管道 -> 父进程
    2.父进程os.read()会等待子进程在管道上发送数据(阻塞)
    '''
    import os,sys,time
    def child(pw):
        time.sleep(5)
        msg='child processing'
        os.write(pw,msg.encode())       #将msg写入文件描述符pw
    def parent():
        r,w = os.pipe()
        if os.fork() == 0:
            #child processing
            child(w)
        else:
            msg = os.read(r,32)         #主线程监听管道,每次有数据则继续执行
            print(msg)
    parent()

    双向匿名管道

    ...

     

    multiprocessing模块的管道

    '''
    1.multiprocessing的管道默认是双向的
    '''
    import os
    from multiprocessing import Process,Pipe
    def sender(pipe):
        #单工
        pipe.send('i,am a child(sender)')
        pipe.close()
    def talker(pipe):
        #双工
        pipe.send('i,am a child(talker)') #向父进程发送消息 (子->父)
         res= pipe.recv()                 #获得父进程的回复消息 (父->子)
        print('msg from parent: ' + res)
    if __name__=='__main__':
        #单工模式
        parentEnd,childEnd = Pipe()
        p = Process(target = sender,args=(childEnd,))
        p.start()
        print('msg from child(sender): '+ parentEnd.recv())
        parentEnd.close()
    
        #双工模式
        parentEnd,childEnd = Pipe()
        c = Process(target = talker,args=(childEnd,))
        c.start()
        print('msg from child(talker)' + parentEnd.recv())
        parentEnd.send('i,am a parent response')
        c.join() #等待子进程执行完毕,否则后面的打印可能会出现在不可预料的地方
        print('end')

     

     

     

    4.命名管道

    ...

    5.套接字

    概述

    源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字。

    套接字,是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定

     基本操作

    '''
    1.程序实现了服务端功能、客户端
    2.在一个新线程里面启动服务端
    3.在另外5个线程里面运行客户端
    '''
    from socket import socket , AF_INET,SOCK_STREAM
    port = 50008
    host='localhost'
    def server():
        sock = socket(AF_INET,SOCK_STREAM)
        sock.bind(('',port))
        sock.listen(5)
        while True:
            conn,addr=sock.accept()  #产生阻塞,直到有新的连接
            data = conn.recv(1024)
            reply = 'server got :[%s]' % data
            conn.send(reply.encode())
    def client(name):
        sock = socket(AF_INET,SOCK_STREAM)
        sock.connect((host,port))
        sock.send(name.encode())
        reply = sock.recv(1024)
        sock.close()
        print('client got :[%s]' % reply)
    if __name__ == '__main__':
        from threading import Thread
        sthread = Thread(target = server)
        sthread.daemon = True
        sthread.start()
        print('server start')
        for i in range(5):
            Thread(target=client,args=('client%s' % i,)).start()

    6.信号

    7.共享内存和全局对象

    8.队列和子类

    参考:

    https://blog.csdn.net/qq_38410730/article/details/81569852

    https://www.cnblogs.com/markleilei/p/6343672.html

  • 相关阅读:
    CentOS 6.4 x64 zabbix 2.2.2 编译安装
    Monitorix 监控 安装配置
    CentOS 6.4 x64 Percona-Server-5.6.15 源码安装
    CentOS 6.4 x64 安装 配置 Redmine 2.4.1
    ActiviMQ的基本使用
    Java内存 模型理解
    线程池的两种创建方式及区别
    线程创建的三种方式及区别
    Spring cloud 之Ribbon(二)负载均衡原理
    Spring cloud 之Ribbon(一)基本使用
  • 原文地址:https://www.cnblogs.com/remly/p/11391090.html
Copyright © 2020-2023  润新知