加入收藏 | 设为首页 | 会员中心 | 我要投稿 百客网 - 百科网 (https://www.baikewang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Unix > 正文

进程间通信都有哪些方法?

发布时间:2022-10-10 11:05:51 所属栏目:Unix 来源:
导读:  目录

  一、什么是进程间通信?

  二、管道

  三、本地内存共享

  四、本地消息/队列

  五、远程调用

  六、消息队列

  七、问题

  7.1 进程间通信都有哪些方法
  目录
 
  一、什么是进程间通信?
 
  二、管道
 
  三、本地内存共享
 
  四、本地消息/队列
 
  五、远程调用
 
  六、消息队列
 
  七、问题
 
  7.1 进程间通信都有哪些方法?
 
  一、什么是进程间通信?
 
  进程间通信(Intermediate Process Communication,IPC)。所谓通信就是交换数据。所以,狭义地说,就是操作系统创建的进程们之间在交换数据。
 
  我们今天不仅讨论狭义的通信,还要讨论 IPC 更广泛的意义——程序间的通信。
 
  程序可以是进程,可以是线程,可以是一个进程的两个部分(进程自己发送给自己),也可以是分布式的——总之,今天讨论的是广义的交换数据。
 
  二、管道
 
  管道提供了一种非常重要的能力,就是组织计算。进程不用知道有管道存在,因此管道的设计是非侵入的。程序员可以先着重在程序本身的设计,只需要预留响应管道的接口,就可以利用管道的能力。比如用shell执行MySQL语句,可能会这样:
 
  进程1 | 进程2 | 进程3 | mysql -u... -p | 爬虫进程
  我们可以由进程 1、进程 2、进程 3 计算出 MySQL 需要的语句,然后直接通过管道执行。MySQL经过计算将结果传给一个爬虫进程,爬虫就开始工作。MySQL并不是设计用于管道,爬虫进程也不是设计专门用于管道,只是程序员恰巧发现可以这样用,完美地解决了自己的问题,比如:用管道构建一个微型爬虫然后把结果入库。
 
  我们还学过一个词叫作命名管道。命名管道并没有改变管道的用法。相比匿名管道,命名管道提供了更多的编程手段。比如:
 
  进程1 > namedpipe进程2 > namedpipe
 
  上面的程序将两个进程的临时结果都同时重定向到 namedpipe,相当于把内容合并了再找机会处理。再比如说,你的进程要不断查询本地的 MySQL,也可以考虑用命名管道将查询传递给 MySQL,再用另一个命名管道传递回来。
 
  这样可以省去和 localhost 建立 TCP 3 次握手的时间。 当然,现在数据库都是远程的了,这里只是一个例子。
 
  管道的核心是不侵入、灵活,不会增加程序设计负担,又能组织复杂的计算过程。
 
  三、本地内存共享
 
  同一个进程的多个线程本身是共享进程内存的。 这种情况不需要特别考虑共享内存。如果是跨进程的线程(或者理解为跨进程的程序),可以考虑使用共享内存。内存共享是现代操作系统提供的能力, Unix 系操作系统,包括 Linux 中有 POSIX 内存共享库——shmem。(如果你感兴趣可以参考网页中的内容)
 
  Linux 内存共享库的实现原理是以虚拟文件系统的形式,从内存中划分出一块区域,供两个进程共同使用。看上去是文件,实际操作是内存。
 
  共享内存的方式,速度很快,但是程序不是很好写,因为这是一种侵入式的开发,也就是说你需要为此撰写大量的程序。比如如果修改共享内存中的值,需要调用 API。如果考虑并发控制,还要处理同步问题等。
 
  因此,只要不是高性能场景,进程间通信通常不考虑共享内存的方式。
 
  四、本地消息/队列
 
  内存共享不太好用,因此本地消息有两种常见的方法。一种是用消息队列——现代操作系统都会提供类似的能力。Unix 系可以使用 POSIX 标准的 mqueue。另一种方式,就是直接用网络请求,比如 TCP/IP 协议,也包括建立在这之上的更多的通信协议
 
  本质上,这些都是收/发消息的模式。进程将需要传递的数据封装成格式确定的消息,这对写程序非常有帮助。程序员可以根据消息类型,分门别类响应消息;也可以根据消息内容,触发特殊的逻辑操作。在消息体量庞大的情况下,也可以构造生产者队列和消费者队列,用并发技术进行处理。
 
  五、远程调用
 
  远程调用(Remote Procedure Call,RPC)是一种通过本地程序调用来封装远程服务请求的方法。
 
  RPC从一台机器(客户端)通过参数传递的方式调用另一台机器(服务器)的方法(服务)并得到返回结果。
 
  程序员调用 RPC 的时候,程序看上去是在调用一个本地的方法,或者执行一个本地的任务,但是后面会有一个服务程序(通常称为 stub),将这种本地调用转换成远程网络请求。 同理,服务端接到请求后,也会有一个服务端程序(stub),将请求转换为一个真实的服务端方法调用。
 
  你可以观察上面这张图unix进程通信,表示客户端和服务端通信的过程,一共是 10 个步骤,分别是:
 
  客户端调用函数(方法);stub 将函数调用封装为请求;客户端 socket 发送请求,服务端 socket 接收请求;服务端 stub 处理请求,将请求还原为函数调用;执行服务端方法;返回结果传给 stub;stub 将返回结果封装为返回数据;服务端 socket 发送返回数据,客户端 socket 接收返回数据;客户端 socket 将数据传递给客户端 stub;客户端 stub 把返回数据转义成函数返回值。
 
  RPC 调用过程有很多约定, 比如
 
  上面这些问题比较棘手,因此在实战中通常的做法是使用框架。
 
  Thrift 框架(Facebook 开源)Dubbo 框架(阿里开源)grpc(Google 开源)
 
  这些 RPC 框架通常支持多种语言,这需要一个接口定义语言支持在多个语言间定义接口(IDL)。
 
  RPC 调用的方式比较适合微服务环境的开发,当然 RPC 通常需要专业团队的框架以支持高并发、低延迟的场景。不过,硬要说 RPC 有额外转化数据的开销(主要是序列化),也没错,但这不是 RPC 的主要缺点。
 
  RPC 真正的缺陷是增加了系统间的耦合。当系统主动调用另一个系统的方法时,就意味着在增加两个系统的耦合。长期增加 RPC 调用,会让系统的边界逐渐腐化。这才是使用 RPC 时真正需要注意的东西。
 
  六、消息队列
 
  既然 RPC 会增加耦合,那么怎么办呢——可以考虑事件。事件不会增加耦合,如果一个系统订阅了另一个系统的事件,那么将来无论谁提供同类型的事件,自己都可以正常工作。系统依赖的不是另一个系统,而是某种事件。如果哪天另一个系统不存在了,只要事件由其他系统提供,系统仍然可以正常运转。
 
  另一个用到消息队列的场景是纯粹大量数据的传输。
 
  比如日志的传输,中间可能还会有收集、清洗、筛选、监控的节点,这就构成了一个庞大的分布式计算网络。
 
  总的来说,消息队列是一种耦合度更低,更加灵活的模型。但是对系统设计者的要求也会更高,对系统本身的架构也会有一定的要求。
 
  具体场景的消息队列有 Kafka,主打处理 feed;
 
  RabbitMQ、ActiveMQ、 RocketMQ 等主打分布式应用间通信(应用解耦)
 
  七、问题7.1 进程间通信都有哪些方法?
 
  可以从单机和分布式角度给面试管阐述。
 

(编辑:百客网 - 百科网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章