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中的通信机制的更多相关文章

  1. 在本机eclipse中创建maven项目,查看linux中hadoop下的文件、在本机搭建hadoop环境

    注意 第一次建立maven项目时需要在联网情况下,因为他会自动下载一些东西,不然突然终止 需要手动删除断网前建立的文件 在eclipse里新建maven项目步骤 直接新建maven项目出了错      ...

  2. 复制docker容器中的nginx某个文件到linux中

    前提:docker容器中的nginx要开启

  3. Windows中查找命令的路径 (类似Linux中的which命令)

    where is a direct equivalent: C:\Users\Joey>where cmdC:\Windows\System32\cmd.exeNote that in Powe ...

  4. Linux 中直接 I/O 机制的介绍

    https://www.ibm.com/developerworks/cn/linux/l-cn-directio/ 对于传统的操作系统来说,普通的 I/O 操作一般会被内核缓存,这种 I/O 被称作 ...

  5. Linux管道的实现机制

    7.1.1 Linux管道的实现机制 在Linux中,管道是一种使用非常频繁的通信机制.从本质上说,管道也是一种文件,但它又和一般的文件有所不同,管道可以克服使用文件进行通信的两个问题,具体表现为: ...

  6. [转帖]Linux 中的零拷贝技术,第 1 部分

    Linux 中的零拷贝技术,第 1 部分 https://www.ibm.com/developerworks/cn/linux/l-cn-zerocopy1/index.html   引言 传统的 ...

  7. Linux 中的零拷贝技术,第 1 部分

    概述 本系列由两篇文章组成,介绍了当前用于 Linux 操作系统上的几种零拷贝技术,简单描述了各种零拷贝技术的实现,以及它们的特点和适用场景.本文是本系列文章的第一部分,主要是介绍一些零拷贝技术的相关 ...

  8. linux中断的下半部机制

    一.中断处理为什么要下半部?Linux在中断处理中间中断处理分了上半部和下半部,目的就是提高系统的响应能力和并发能力.通俗一点来讲:当一个中断产生,调用该中断对应的处理程序(上半部)然后告诉系统,对应 ...

  9. <实训|第十一天>学习一下linux中的进程,文件查找,文件压缩与IO重定向

    [root@localhost~]#序言 在今后的工作中,运维工程师每天的例行事务就是使用free -m,top,uptime,df -h...每天都要检查一下服务器,看看是否出现异常.那么今天我们就 ...

随机推荐

  1. Unity3D AssetBundles 动态加载游戏资源

    AssetBundles are files which you can export from Unity to contain assets of your choice. These files ...

  2. 警告Conversion specifies type'int' but the argument has type'size_t'

    代码: #import<Foundation/Foundation.h> int main(int argc,const char * argv[]){ const char *words ...

  3. UBI文件系统简介

    转:http://www.embedu.org/Column/Column102.htm 在linux-2.6.27以前,谈到Flash文件系统,大家很多时候多会想到cramfs.jffs2.yaff ...

  4. How to Use Auto Layout in XCode 6 for iOS 7 and 8 Development

    The Auto Layout is available on the Storyboard for iOS or OS X development since XCode 5. But, I did ...

  5. 【Git】windows上git命令中文乱码的问题

    windows上git命令中文乱码的问题解决 1.打开git bash快捷方式启动 2.右键 options 3.进入text选项卡,选中中文 和UTF-8 4.应用 测试[中文正常显示] 尝试打开文 ...

  6. ios frame,bound和center

    frame:指的是视图在父视图的坐标系统中的大小和位置. bound:指的是视图在试图本身的坐标系统中的大小(位置起点是原点). center:指的是视图在父视图坐标系统中的中心点. 贴张苹果官网的图 ...

  7. this的四种绑定规则总结

    一.默认绑定 1.全局环境中,this默认绑定到window 2.函数独立调用时,this默认绑定到window console.log(this === window);//true functio ...

  8. shell中declare命令

    declare命令有如下选项: -a 声明一个数组 -i 声明一个整型 -f 打印所有函数定义 -F 仅打印函数名字 -r 声明一个readonly变量,该变量的值无法改变,并且不能为unset -x ...

  9. 使用JMeter录制手机App脚本

    Apache JMeter是100%的Java桌面应用程序,用于对软件做压力测试.它最初被设计用于Web应用测试,但后来扩展到其他测试领域.现如今这款软件越来越受到测试人员的青睐,相比于LoadRun ...

  10. 【转载】json对象的使用

    使用JSON 进行数据传输 一.选择的意义 在异步应用程序中发送和接收信息时,可以选择以纯文本和 XML 作为数据格式.为了更好的使用ajax, 我们将学习一种有用的数据格式 JavaScript O ...