终于有人将进程间通信讲明白了


使用多进程协作来实现应用和系统是一种被广泛使用的开发方法。多进程协作主要有以下三点优势。

  • 将功能模块化,避免重复造轮子。

  • 增强模块间的隔离,提供更强的安全保障。

  • 提高应用的容错能力。

进程间通信(Inter-Process Communication,IPC)则是多进程协作的基础。一般而言,IPC至少需要两方(如两个进程)参与。根据信息流动的方向,这两方通常被称为发送者和接收者。在实际使用中,IPC经常被用于服务调用,因此参与IPC的两方又被称为调用者和被调用者,或者客户端和服务端。

图7-1是一个简单的IPC设计。它假设内核已为两个进程映射了一段共享内存,且共享内存刚好可以存放两个消息(发送者消息和接受者消息)。

 

 

01 进程间通信的重要功能

  • 数据传递:消息传递(message passing)是IPC中常用的数据传递方式,即将数据抽象成一个个的消息进行传递。不同的IPC设计有不同的消息抽象,且消息传递往往需要一个“中间人”(如共享内存)。

  • 控制流转移:当一个通信发生时,内核将控制流从发送者进程切换到接收者进程(返回的过程类似)。IPC中的控制流转移,通常是利用内核对进程的运行状态和运行时间的控制来实现的。

 

02 进程间通信的分类

  • 单向IPC、双向IPC、单/双向IPC:单向IPC通常指消息在一个连接上只能从一端发送到另一端,双向IPC则允许双方互相发送消息。而单/双向IPC则会根据通信中具体的配置选项等来判断是否需要支持单向或双向的通信。实际中,很多系统选择的是单/双向IPC,这样可以比较好地支持各种场景。当然,如管道、信号等只支持单向IPC的机制在实际中同样有较多的应用。

  • 同步IPC和异步IPC:简单来看,同步IPC指它的IPC操作(如Send)会阻塞进程直到该操作完成;而异步IPC则通常是非阻塞的,进程只要发起一次操作即可返回,而不需要等待其完成。相比异步而言,同步IPC有着更好的编程抽象。然而同步IPC在操作系统的发展中,逐渐表现出一些不足。一个典型的问题是并发。总的来看,目前大部分操作系统内核都会选择同时实现同步和异步IPC,以满足不同的应用需求。

 

03 进程间通信的相关机制

  • 超时机制:超时机制扩展了IPC通信双方的接口,允许发送者/接收者指定它们发送/接收请求的等待时间。比如,一个应用程序可以花费5秒等待文件系统进程的IPC请求处理操作。如果超过5秒仍然没有反馈,则由操作系统内核结束这次IPC调用,返回一个超时的错误。

  • 通信连接管理:对于基于共享内存的进程间通信方案,通信连接的建立通常是在建立共享区域的一瞬间完成的;而对于涉及内核的控制流转移的通信而言,通信连接管理是内核IPC模块的很重要的一部分。虽然实际的系统中会有各种不同的实现,但是它们大部分可以被归为两类——直接通信和间接通信。直接通信是指通信的进程一方需要显式地标识另一方。间接通信需要经过一个中间的信箱来完成通信,每个信箱有自己唯一的标识符,而进程间通过共享一个信箱来交换消息。

  • 权限检查:进程间通信通常依赖于一套权限检查的机制来保证连接的安全性。例如,seL4等微内核系统中的Capability机制,会将所有的通信连接抽象成一个个的内核对象。而每个进程对内核对象的访问权限(以及能够在该内核对象上执行的操作)由Capability来刻画。当一个进程企图和某其他进程通信时,内核会检查该进程是否拥有一个Capability,是否有足够的权限访问一个连接对象并且对象是指向目标进程的。类似地,宏内核,如Linux系统,通常会复用其有效用户/有效组的文件权限,以刻画进程对于某个连接的权限。

  • 命名服务:命名服务像是一个全局的看板,可以协调服务端进程和客户端进程之间的信息。简单来说,服务端进程可以将自己提供的服务告诉命名服务进程,比如文件系统进程可以注册一个“文件系统服务”,网络系统进程可以注册一个“网络服务”。而客户端进程可以去命名服务上查询当前的服务,并选择自己希望建立连接的服务去尝试获取权限。具体是否分发权限给对应的客户端进程,是由命名服务和对应的服务端进程根据特定的策略来判断的。

 

04 宏内核进程间通信

宏内核下的典型的进程间通信机制,具体包括管道,System V中的消息队列、信号量、共享内存,Linux信号机制,以及套接字机制(socket)。

宏内核操作系统中进程间通信更多的是应用之间的交互,因此,设计的重心通常会放在接口的易用性、稳定性等方面。图7-5给出了典型的宏内核进程间通信机制的对比。可以看到,虽然在IPC的几个设计角度上几个方案都各有异同,但是它们之间的主要区别是在数据抽象上。在实际的应用中,虽然多种IPC方案都可以作为通信的选择,但是应用程序往往会根据对数据抽象的需求来选择具体的方案。

 

 

05 微内核进程间通信

由于进程间通信对于微内核系统性能的重要意义,大部分微内核操作系统都会优先从性能角度来设计和实现进程间通信。

Mach:早期的微内核进程间通信设计

Mach通过两种基本的抽象——端口(port)和消息(message),设计和实现了一种间接通信IPC:通信的双方不需要显式指定另一方,而是通过端口进行通信(对应于“信箱”)。进程之间通过端口流通的数据就是消息。

作为一个早期的微内核系统,Mach系统的性能比起当时的宏内核系统(如UNIX)还是存在不小的差距。其中一个原因是Mach为了实现大量的目标,如可裁剪性、可移植性等,导致其内核复杂,且代码量较大。不过,Mach的IPC设计仍对后来的很多系统有着非常重大的影响。Mach中端口和消息的设计使得进程间的通信和具体的进程是隔离开的。只要一个进程拥有某个端口,其就能够通过这个端口和“另一端”的进程进行通信。后续的微内核系统设计大都考虑了Mach的思想,不管是借鉴其设计还是将其缺陷引以为戒。

 

L4:围绕进程间通信优化而设计的微内核系统

根据Mach的经验,Liedtke等研究人员开始研发L4系列的微内核系统。L4系列微内核系统的一个突出思路是:进程间通信是微内核的核心功能,需要围绕通信去完成整个系统的设计和实现。L4是当下仍然十分主流的微内核系统,特别是后续衍生出了各种变体和相关的系统。

在L4微内核中,内核只保留了基本的功能,包括地址空间、线程、进程间通信等,并且不考虑如兼容性等要求,而是选择针对特定硬件做极致的性能优化。这样做的好处就是内核的代码量非常少,可以把少量的功能尽可能支持好。

 

LRPC:迁移线程模型

迁移线程(thread migration)是一个比较“极端”的优化性能的IPC设计。截止到目前,我们了解到优化IPC性能的大部分工作会关注两个部分:优化控制流切换的性能和优化数据传输的性能。迁移线程认为,其他的IPC设计可以看成将需要处理的数据发送到另一个进程并让其处理。这也是为什么控制流切换和数据传输会成为主要的瓶颈。如果换一个角度,将另一个进程处理数据的代码拉到当前进程,那么我们是不是可以避免控制流的切换(仍然是当前进程处理)以及数据传输(数据已经准备在当前进程中)呢?迁移线程就是围绕这个新的视角进行设计的。

迁移线程方案被用在LRPC、Mach(优化版本)等系统中,是目前纯软件进程间通信优化中效果最好的设计之一。迁移线程的基本原则是:①简化控制流切换,让客户端线程执行“服务端的代码”;②简化数据传输,共享参数栈和寄存器;③简化接口,减少序列化等开销;④优化并发,避免共享的全局数据结构。其中,前两点原则都基于“将代码拉到本地”这个新的视角。

迁移线程IPC和主流IPC设计的对比如图7-13所示。要做到“将代码拉到本地”,迁移线程首先需要对线程结构进行解耦,明确线程中哪些部分是对通信请求处理起关键作用的。然后,这部分允许被调用者(负责处理请求的逻辑)运行在调用者的上下文中,将跨进程调用变成更接近函数调用的形式。

 

如果使用迁移线程模型,在进程间通信过程中,内核不会阻塞调用者线程,但是会让调用者线程执行被调用者的代码。整个过程没有被调用者线程被唤醒,相反,被调用者端更像是一个“代码提供者”。此外,内核不会进行完整的上下文切换,而是只切换地址空间(页表)等和请求处理相关的系统状态。其中,不会涉及线程和优先级的切换,也不会调用调度器。迁移线程的优点在于减少了内核调度的时间,并简化了内核中的IPC处理。在多核场景下,迁移线程方案还可以避免跨核通信引入的开销。

 

06 案例分析:Android Binder

在Android场景下,进程间通信在大部分情况下做的其实是“远程过程调用”。服务端进程负责提供具体的服务,客户端进程则通过进程间通信来发起服务请求,并获得服务端进程处理后的结果。除了通信双方进程外,在Binder IPC中还引入了一个Context Manager进程。Context Manager提供命名服务,它的任务是建立通信连接。在Binder IPC的内核设计中,提供了句柄(handle)的抽象来表示IPC对象(即一个通信连接)。句柄和我们熟悉的文件描述符其实很相似,用户通过对句柄的操作来发起对特定进程的通信。

和之前的进程间通信设计不同的一点是,Binder IPC中采用了“线程池”的服务端模型。也就是说,在服务端中,Binder的用户态和内核会有一个响应线程池的概念。当某个客户端进程发起通信时,内核会从(服务端的)线程池中选择一个可用的线程来响应。这种设计能够在同步进程间通信的情况下比较好地处理并发的通信请求。

本文节选自《现代操作系统:原理与实现》第7章

操作系统和系统安全领域国际知名学者、上海交通大学陈海波夏虞斌领衔撰写;

本书是作者在复旦大学和上海交通大学十余年操作系统教学经验的科学总结,由浅入深介绍现代操作系统经典理论与方法。结合前沿研究与工业界实践,面向真实场景与真实问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466887.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神舟本本放心率

总得票8520 可以放心购买 22.0% 1942票 不太放心 64.0% 5510票 看情况 12.0% 1068票投票起止时间:2007-11-15 至2008-11-22转载于:https://www.cnblogs.com/badapple126/archive/2007/11/16/962020.html

梯度下降算法

在学习逻辑回归时,对梯度上升算法进行了应用,看到其他的博客讲解,梯度上升算法适合求最大值,梯度下降算法适合求最小值,这里有一个分析:梯度上升算法公式是学习率,是一个常数。这个是根据逻辑回…

花了一个深夜,才用C语言写了一个2048游戏雏形

12年我毕业的第二个月工资,我就买了一个IPAD,然后在IPAD上下了一个2048游戏,玩起来非常爽。然后这几天看到好几个公众号都发了自己写这个游戏的代码,然后我自己也想试试,所以就有了这篇文章,写代码还是很有…

向银行贷款20万, 分期三年买50万的车,个人借款40万, 贷款10年买200万的房子,再贷款120万分创业...

向银行贷款20万按1年期贷款利率为:6%,若按年还贷款,银行贷款利息为:200,000*6%12,000。连本带息:20*106%21.2万分期三年买50万的车 贷款总额30万 年利率按10%算,分三年还清&#xff…

集成算法——Adaboost代码

集成算法是我们将不同的分类器组合起来,而这种组合结果就被称为集成方法或者是元算法。使用集成方法时会有多种形式:可以是不同算法的集成,也可以是同意算法在不同设置下的集成,还可以是数据集不同部分分配给不同分类器之后的集成…

年终抽奖来了

时间很快,2020年已经到了12月份,我从2018年开始写公众号,经过了快两年是时间,我收获了4万的读者,非常开心。我自己是一个挺逗逼的人,而且我写公众号并不觉得我比别人厉害,技术上我真的就是一个很…

嵌入式 Linux下永久生效环境变量bashrc

作者:skdkjxy原文:http://blog.sina.com.cn/s/blog_8795b0970101f1f9.html.bashrc文件 在linux系统普通用户目录(cd /home/xxx)或root用户目录(cd /root)下,用指令ls -al可以看到4个隐藏文件&am…

回归分析——线性回归

机器学习中,对于离散的数据可以做分类问题,那对于连续的数据就是做回归问题,这里对一元线性回归和多元线性回归做一个简介,帮组理解。回归分析:从一组样本数据出发,确定变量之间的数学关系式,对…

编译原理(五)自底向上分析之算符优先分析法

自底向上分析之算符优先分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记。 基本过程 1. 一般方法:采用自左向右地扫描和分析输入串,从输入符号串开始,通过反复查找当前句型的句柄&#xff0…

做Android开发,要清楚init.rc里面的东西

init.rc 复习看这个之前,先看看大神总结的文章这篇文章总结的非常到位,但是因为代码不是最新的Android版本,对我们最新的Android版本不适用。http://gityuan.com/2016/02/05/android-init/#init rc文件拷贝拷贝其实也就是把文件放到机器的某个…

宏比较值,坑的一B

昨晚上,我准备睡觉,连总给我发了一段代码#include "stdio.h"#define MAX_MACRO(a, b) ((a) > (b) ? (a) : (b)) int MAX_FUNC(int a, int b) {return ((a) > (b) ? (a) : (b)); }int main() {unsigned int a 1;int b -1;printf(&quo…

Linux下Samba服务器搭建

linux文件共享之samba服务器 ——ubuntu 宗旨:技术的学习是有限的,分享的精神是无限的。 关闭LINUX防火墙命令: #ufwdisable 然后就在windows下ping一下linux的IP,如果能ping通,就可以继续下面的内容,如果p…

搞懂C++为什么难学,看这篇就够了!

学C能干什么? 往细了说,后端、客户端、游戏引擎开发以及人工智能领域都需要它。往大了说,构成一个工程师核心能力的东西,都在C里。跟面向对象型的语言相比,C是一门非常考验技术想象力的编程语言,因此学习起…

看图学源码之FutureTask

RunnableFuture 源码学习: 成员变量 任务的运行状态的转化 package java.util.concurrent; import java.util.concurrent.locks.LockSupport;/**可取消的异步计算。该类提供了Future的基本实现,包括启动和取消计算的方法,查询计算是否完成以…

单片机的引脚,你都清楚吗?

第1课:单片机简叙1.单片机可以做什么?目前单片机渗透到我们生活的各个领域,几乎很难找到哪个领域没有单片机的踪迹。小到电话,玩具,手机,各类刷卡机,电脑键盘,彩电,冰箱&…

Graphviz的安装及纠错

在Anaconda Prompt里边输入conda install graphviz 安装成功之后输入pip install graphviz 它会提示成功安装。 启动 Jupyter Notebook ,在文件里边输入 import graphviz 测试,如果没有报错证明,模块安装成功,但是在运行程序…

sklearn——决策树

总结sklearn决策树的使用,方便以后查阅。1.分类决策树 (基于CART树) 原型:参数:2、回归分类树 原型:参数:3、export_graphviz 当训练完毕一颗决策树时,可以通过sklearn.tree.expor…

Linux下SVN服务器的搭建

Linux下SVN服务器的搭建 宗旨:技术的学习是有限的,分享的精神是无限的。 1、下载工具(下载地址:) subversion-1.6.1.tar.gz subversion-deps-1.6.1.tar.gz 2、解压两个包: a) tar -xzvf subvers…

记一次解决问题的掉坑过程

这两天在调试一个音频ADC 芯片,也是之前的项目,但是一直调不出来,我发现我总是在这样的问题上纠结很久,以前踩过的坑后面照样会踩,只不过踩完会迅速把脚拉出来继续前进,我经常听到有人说「做嵌入式真的太容…

sklearn——AdaBoost应用

选自《python大战机器学习》