Android中的常见通信机制和Linux中的通信机制
Handler
Handler是Android系统中的一种消息传递机制,起作用是应对多线程场景。将A进程的消息传递给B线程,实现异步消息处理。很多情况是将工作线程中需要更新UI的操作消息传递给UI主线程,而实现更新UI操作。
因为工作线程和主线程是共享地址空间,即Handler实例对象mHandler位于线程间共享的内存堆上,工作线程和主线程直接使用该对象,只需要注意多线程的同步问题。工作系统通过mHandler向其成员变量MessageQueue中添加Message,而主线程一直处于loop中,当收到新的message时,按照一定规则分发给相应的handlerMessage方法来处理。
Handler用于同进程的线程间通信的核心是线程间共享内存空间,而不同矜持拥有不同的地址空间,也就无法使用handler来实现进程间通信。如图1所示,为Handler消息通信架构图。
图中,首先Handler通过sendMessage()发送Message到MessageQueue队列,Looper通过looper()不断提取出达到触发条件的Message,并将Message交给target来处理;然后通过displatchMessage()分发给handlerMessage处理。
将Message添加到MessageQueue时,会往管道中写入字符,这样就回唤醒loop线程;如果MessageQueue中没有Message,并处理idle状态,则会执行idleHandler接口中的方法,往往用于做一些清理性的工作。关于消息分发的优先级:
- Message回调分发:message callback.run()优先级最高。
- Handler回调分发:Handler.mCallback.handleMesage(msg),优先级次之。
- Handler默认分发:Handler.handlerMessage(msg),优先级最低。
Binder
概述
Android中一般每个应用对于一个进程,而涉及到每个应用之间的通信,即进程间通信,Android中采用的最多的IPC机制为Binder机制。首先我们介绍下IPC机制原理,如图2所示为从进程角度阐述了IPC机制。从图中可以看出,每个Android进程只能运行在自己所有的虚拟地址空间中。对于一个4G的虚拟地址空间,假设用户空间为3G,内核空间为1G(可修改)。进程在用户空间的数据是不可共享的,在内存空间中则可共享。Client进程想server进程发送信息,即利用内核空间可共享机制完成。
- 从IPC角度:Binder是Android中的一种跨进程通信方法,该方法是Android系统独有的。
- 从Android Driver层:Binder还可以理解为一种虚拟的物理设备,设备驱动为/dev/binder。
- 从Android native层:Binder是创建Service Manager以及BpBinder/BBinder模型,大家与Binder驱动的桥梁。
- 从Android frameworks层:Binder是各种Manager(ActivityManager、WindowManager)和相应xxxManagerService的桥梁。
- 从APP层:Binder是客户端和服务端进程通信的媒介,当bindServicer时,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获得服务端提供的服务(包括普通服务和基于AIDL的服务)或数据。
架构
如图3所示,为Binder在Android不同层级的位置和关联图,是一种C/S架构的通信机制。在Kernel层,Binder可以看成是一个驱动,其驱动架构与其他驱动相同。Native层中ServiceManager会启动一个Binder的守护进程,ServiceManager功能简单,包括获取服务、注册服务,大部分同行通过都存在于BpBinder和BBinder之间。Framework层的Binder逻辑是建立在Native层架构基础上的,核心逻辑都是交给Native层来处理。但需要注意下frameworks层的Binder逻辑是建立在Native层架构基础上的,核心逻辑都是交给Native层来处理。但需要注意下frameworks层的ServiceManager和Native层的ServiceManager功能并不对应,其最终实现是通过BinderProxy传递给Native层来完成的。
Socket
Socket通信也是基于C/S架构,但相比Binder要简单一些。首先我们来回顾下TCP/IP协议的知识。TCP/IP协议是一个四层的体系结构:应用层、传输层、网络层、网络接口层。在传输层中又有TCP和UDP两个协议。Socket是工作与TCP/IP协议中应用层和传输层之间的一种抽象。Android系统中,又分为流套接字和数据报套接字。其中流套接字将TCP协议作为其端对端协议,提供了一个可信赖的字节流是服务;数据报套接字使用UDP协议,提供数据打包发送服务。在Android系统中使用Socket通信的场景包括:
- Zygote:fork新进程,system_server向zygote发送fork新进程请求是使用socket通信。
- Installd:用户安装app的守护进程,PMS安装应用时向installd发送socket通信来完成安装过程。
- Adbd:用于服务adb操作。
- Logcatd:用于服务logcat操作
- Vold:存储类守护进程,用于服务USD、sdcard等存储设备的事件处理。(在Android9.0中已将这一进程通信修改为Binder实现)
其他几种通信机制
管道
Linux支持的最初Unix IPC机制之一,特点是:
- 管道是半双工,数据只能向一个方向流动,需要双方通信时,建议使用两个管道。
- 只能用于父子进程或者兄弟进程之间。
- 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且每次都是从缓冲区都不读出数据。
- 数据读出和写入;一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区头部读出数据。
消息队列
消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。每个数据块都被认为含有一个类型,接受进程可以独立地接受含有不同类型的数据结构。通过发送消息来避免明明管道的同步和阻塞问题。消息队列发送的消息有最大长度限制。
共享内存
共享内存,顾名思义即允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递的一种非常有效的方法。不同进程之间共享的内存通常安排为同一段物理内存。进程可以讲同一段共享内存链接到他们自己的地址空间中。所有进程都可以访问共享内存中的地址。
需要注意的是:共享内存没有使用同步机制,即进程A对共享内存进程写操作时,并没有对共享内存加锁,进程B仍然可以读取共享内存中的数据。所以通常我们需要使用其他的机制来同步共享内存的访问。
信号量
为了防止出现多个进程同步访问一个共享资源而引发一系列问题,我们需要一种方法,它可以通常生成令牌来授权,在任何时刻只能有一个指向线程访问代码的临界区域。临界区域是指执行数据更新的代码需要独占式执行。而信号量就可以提供这样的一种访问机制,也就是说信号量是用来协调进程对资源共享的访问。
信号量是一个特殊变量,程序对其访问都是原子操作,且只允许对它进程等待和发送信息操作。最简单的信号量是只能取0和1的变量。这也是信号量最常见的形式。这就是二进制信号量。而中可以取多个正整数的信号量称为通用信号量。
信号
信号是UNIX和Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会响应地采取一些行动。通常信号是由一个错误产生的。但他们还可以作为进程间通信或修改行为的一种形式,明确地由一个进程发送给另一个进程。信号产生叫做生成,接收叫做信号捕获。
Android中几种IPC机制对比
名称 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
Bundle | 简单易用 | 只能传输Bundle支持的数据类型 | 组件间进程间通信 |
文件共享 | 简单易用 | 不适合并发场景,并且无法做到进程间即时通信 | 无并发访问情形,交换简单数据实时性不高的场景 |
AIDL | 功能强大,支持一对多并发通信,支持实时通信 | 使用复杂,需要处理好线程同步 | 一对多通信且有RPC需求 |
Message | 功能一般,支持一对多串行通信,支持实时通信 | 不能很好处理高并发场景,不支持RPC,数据通过Message进程传输,因此只能传输Bundle支持的数据类型 | 低并发的一对多即时通信,无RPC需求,或者无需要返回结果的RPC需求 |
ContentProvider | 在数据访问方面功能强大,支持一对多并发数据共享,可通过Call方法扩展其他操作 | 可以理解为受约束AIDL,主要提供数据源的CRUD操作 | 对多进程间的数据共享 |
socket | 功能强大,可以使用网络传输字节流,支持一对多并发实时通信 | 实现细节稍微有点繁琐,不支持直接RPC | 网络数据交换,或少数进程间交换 |
Android中的常见通信机制和Linux中的通信机制的更多相关文章
- 在本机eclipse中创建maven项目,查看linux中hadoop下的文件、在本机搭建hadoop环境
注意 第一次建立maven项目时需要在联网情况下,因为他会自动下载一些东西,不然突然终止 需要手动删除断网前建立的文件 在eclipse里新建maven项目步骤 直接新建maven项目出了错 ...
- 复制docker容器中的nginx某个文件到linux中
前提:docker容器中的nginx要开启
- Windows中查找命令的路径 (类似Linux中的which命令)
where is a direct equivalent: C:\Users\Joey>where cmdC:\Windows\System32\cmd.exeNote that in Powe ...
- Linux 中直接 I/O 机制的介绍
https://www.ibm.com/developerworks/cn/linux/l-cn-directio/ 对于传统的操作系统来说,普通的 I/O 操作一般会被内核缓存,这种 I/O 被称作 ...
- Linux管道的实现机制
7.1.1 Linux管道的实现机制 在Linux中,管道是一种使用非常频繁的通信机制.从本质上说,管道也是一种文件,但它又和一般的文件有所不同,管道可以克服使用文件进行通信的两个问题,具体表现为: ...
- [转帖]Linux 中的零拷贝技术,第 1 部分
Linux 中的零拷贝技术,第 1 部分 https://www.ibm.com/developerworks/cn/linux/l-cn-zerocopy1/index.html 引言 传统的 ...
- Linux 中的零拷贝技术,第 1 部分
概述 本系列由两篇文章组成,介绍了当前用于 Linux 操作系统上的几种零拷贝技术,简单描述了各种零拷贝技术的实现,以及它们的特点和适用场景.本文是本系列文章的第一部分,主要是介绍一些零拷贝技术的相关 ...
- linux中断的下半部机制
一.中断处理为什么要下半部?Linux在中断处理中间中断处理分了上半部和下半部,目的就是提高系统的响应能力和并发能力.通俗一点来讲:当一个中断产生,调用该中断对应的处理程序(上半部)然后告诉系统,对应 ...
- <实训|第十一天>学习一下linux中的进程,文件查找,文件压缩与IO重定向
[root@localhost~]#序言 在今后的工作中,运维工程师每天的例行事务就是使用free -m,top,uptime,df -h...每天都要检查一下服务器,看看是否出现异常.那么今天我们就 ...
随机推荐
- HNOI2016 游记
题外 忽然想起去年的HNOI2015总结里好像引了一句诗: 此情可待成追忆,只是当时已惘然. Day0 唔,感觉不知道想些什么,只是觉得其实还没有做好准备,想学的东西学的仓促,想复习的东西,也只能看一 ...
- 玩转Nuget服务器搭建(三)
前两篇已经介绍了如何打包.如何搭建nuget server web站点,接下来让我们介绍一下,如何在我们的vs中访问我们自己搭建的nuget服务器中的包. vs访问我们自己的nuget服务器中的包 ...
- po_文件格式[转]
原文: http://cpp.ezbty.org/content/science_doc/po_%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F 摘要:PO 是一种 GNU 定 ...
- 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-通知(Advice)API
本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 让我们看看 Spring.N ...
- Debian下载地址
http://cdimage.debian.org/cdimage/archive/
- [置顶]
docker web-GUI DockerUI和Shipyard对比
DockerUI和Shipyard对比 相似 基于Docker API,提供等同Docker命令行的大部分功能,支持container管理,image管理. web页面查看和管理容器和镜像,均能批量管 ...
- 利用DFS求联通块个数
/*572 - Oil Deposits ---DFS求联通块个数:从每个@出发遍历它周围的@.每次访问一个格子就给它一个联通编号,在访问之前,先检查他是否 ---已有编号,从而避免了一个格子重复访问 ...
- JComboBox添加item的赋值类型问题!不一致的话会导致不能更改jcombobox的选择值
在用swing做页面的时候,往往需要设置字体样式,那么,如何用一种方法设置字体之后,在后面的其他页面就不需要再次设置字体了呢? 下面这个方法就可以解决了: JComboBox在对它进行添加子项的时候, ...
- ElasticSearch获取指定Field数据的Java方法
ElasticSearch(ES)检索后需要结果时,可能通过source接口读出.但是这样的话,返回的结果会很多.在调用search方法时,我们可以添加addfield或addfields方法,仅仅读 ...
- 2017.7.21 linux下进程管理工具supervisord的安装与使用
参考来自:http://blog.haohtml.com/archives/15145 0 操作环境 1 supervisord的介绍 Supervisord是用Python实现的一款非常实用的进程管 ...