1、Android IPC简介

  Inter-Process Communication的缩写就是IPC,含义是进程间通信或是跨进程间通信,是指两个进程进行交换数据的过程。

  • 进程是什么?

  进程在pc上就是一个程序,在Android就是一个应用。线程表示的是cpu调度的最小单元,进程指一个执行单元。一个进程可包含多个线程,也可以只有一个线程。

  所以Android IPC就可以理解为不同应用间的通信,但一个应用也有多进程模式,所以IPC不仅是应用间的通信,不过这个没必要纠结,反正就是跨进程间通信。

2、Android中的多进程模式

  • 开启多线程模式

  我们可以在AndroidManifest中修改Activity的属性,轻易的开启多线程模式。

<activity
  android:name=".MainActivity">
  <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
</activity>
<activity
  android:name=".Main2Activity"
  android:process="com.xw.test" />
<activity
  android:name=".Main3Activity"
  android:process=":test" />

  android:process指定这个属性就可以开启多进程模式,

  将三个Activity依次启动,然后使用adb shell可以看到

  这是MainActivity运行在这个应用的默认进程中,进程名就是包名

  这是Main2Activity运行在com.xw.test中

  这是Main3Activity运行在com.example.administrator.test:test中

  Main3Activity使用的“:”的含义是指要在当前的进程名之前附加上当前的包名。以“:”开头的进程属于当前应用的私有进程,其他应用的组件不可以和它跑在同一进程中,而不以“:”开头的进程属于全局进程,其他应用通过ShareUID方式可以和它跑在同一进程中。

  Android系统会为每一个应用分配一个唯一的UID,具有相同UID的应用才能共享数据,两个应用通过ShareUID方式可以跑在同一进程中还需要签名相同,在这种情况下它们可以互相访问对方的私有数据,比如data目录、组件信息等。

  • 多线程运行机制

  如果新建一个类,这个类中有一个public的静态成员变量,

public class Data {
public static int Id = 1;
}

  然后我们在MainActivity的onCreate中将其赋值为2然后打印出来,然后我们再Main2Activity中直接打印出来。我们会发现原本应该是共享的静态变量,MainActivity修改为2打印也是2,Main2Activity打印还是1.

  其实,android会为每一个应用(或者说线程)分配一个独立的虚拟机,不同的虚拟机在内存分配上有不同的地址空间,也就是说其实MainActivity和Main2Activity访问的但是两个名字相同的变量而已

  一般来说,多进程会造成如下几方面的问题:

  (1) 静态成员和单例模式失效:就上面的这种情况

  (2) 线程同步机制完全失效:已经不是一块内存了,所以无论是锁对象还是锁全局类都无法保证线程同步。

  (3)SharePreferences的可靠性下降:SharePreferences的底层是通过读/写XML文件出现的,并发写显然是会出问题的,甚至并发读/写都有可能出现问题。

  (4)Application会多次创建:当一个组件在跑一个新的进程的时候,分配独立的虚拟机,其实就是启动一个应用的过程,相当于系统把这个应用重启了一遍,就创建了新的Application。

3、Binder

  Binder是Android中的一个类,它实现了IBinder接口,Binder是Android中的一种跨进程通信方式

  Binder是客户端和服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务和数据。

  这里使用AIDL来分析Binder的工作机制,

  先新建一个包并定义一个Book类,并实现Parcelable接口

public class Book implements Parcelable {

    public int bookId;
public String bookName; public Book(int bookId, String bokName){
this.bookId = bookId;
this.bookName = bookName;
} @Override
public int describeContents() {
return 0;
} @Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(bookId);
parcel.writeString(bookName);
} public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>(){ @Override
public Book createFromParcel(Parcel parcel) {
return new Book(parcel);
} @Override
public Book[] newArray(int i) {
return new Book[i];
}
}; private Book(Parcel parcel){
bookId = parcel.readInt();
bookName = parcel.readString();
}
}

  然后再创建Book.aidl和IBookManager.aidl

//Book.aidl
package com.xw.book.aidl; parcelable Book; //IBookManager.aidl
package com.xw.book.aidl; import com.xw.book.aidl.Book; interface IBookManager{
List<Book> getBookList();
void addBook(in Book book);
}

  Book.aidl是Book在AIDL中的声明,IBookManager.aidl是定义的一个接口。

  再点击安装到手机之后,在gen目录下的com.xw.book.aidl包中有一个IBookManager.java的类,这个是系统自动生成的

/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: C:\\Users\\Administrator\\Desktop\\test\\app\\src\\main\\aidl\\com\\xw\\book\\aidl\\IBookManager.aidl
*/
package com.xw.book.aidl;
public interface IBookManager extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.xw.book.aidl.IBookManager
{
private static final java.lang.String DESCRIPTOR = "com.xw.book.aidl.IBookManager";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.xw.book.aidl.IBookManager interface,
* generating a proxy if needed.
*
*/
public static com.xw.book.aidl.IBookManager asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.xw.book.aidl.IBookManager))) {
return ((com.xw.book.aidl.IBookManager)iin);
}
return new com.xw.book.aidl.IBookManager.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
} @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList:
{
data.enforceInterface(DESCRIPTOR);
java.util.List<com.xw.book.aidl.Book> _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook:
{
data.enforceInterface(DESCRIPTOR);
com.xw.book.aidl.Book _arg0;
if ((0!=data.readInt())) {
_arg0 = com.xw.book.aidl.Book.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.xw.book.aidl.IBookManager
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public java.util.List<com.xw.book.aidl.Book> getBookList() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.xw.book.aidl.Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.xw.book.aidl.Book.CREATOR);
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public void addBook(com.xw.book.aidl.Book book) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((book!=null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public java.util.List<com.xw.book.aidl.Book> getBookList() throws android.os.RemoteException;
public void addBook(com.xw.book.aidl.Book book) throws android.os.RemoteException;
}
  • DESCRIPTOR

    Binder的唯一标识,一般使用当前Binderd的类名表示。

  • asInterface(android.os.IBinder obj)

    用于将服务端的Binder对象转换成客户端需要的AIDL接口类型的对象,这种转换是区分进程的,如果服务端和客户端位于同一进程,那么该方法会返回服务端的Stub对象本身,否则返回的是系统封装后的Stub.proxy对象。

  • onTransact

    这个方法运行在服务端的Binder线程池中,当客户端发起跨进程请求时,远程请求会通过系统底层封装后交由此方法来处理, 服务端通过code可以确定客户端请求的目标方法是什么,从data中取出目标方法所需要的参数,然后执行目标方法没目标方法执行完后,就向reply中写入结果如果此方法返回false,那么客户端的请求就会失败

  • Proxy

    这个类中有两个方法分别是getBookList和addBook,两个方法的执行过程是一样的,说一个就行,方法将运行在客户端,先创建该方法所需要的输入型Parcel对象_data、输出型Parcel对象_reply,和返回值对象,然后把该方法的参数信息写入_data,然后调用transact方法来发起RPC(远程过程调用)请求;然后服务端的onTransact方法会被调用,知道RPC过程返回后,当前线程继续执行,并从_reply中取出RPC过程的返回结果,最后返回_reply中的结果

  以上就是Binder的工作机制,然后还有两点需要注意:当客户端发出请求的时候,由于当前线程会被挂起直至服务端进程返回数据,所以如果一个远程方法是很耗时的,那么不能在UI线程中发起此远程请求,其次,由于服务端的Binder方式运行在Binder的线程池中,所以Binder方法不管是否耗时都应该采用同步的方法去实现,因为它已经运行在一个线程中了。

  

Binder的工作机制

  图片来源:http://blog.csdn.net/u012827296/article/details/51259006

参考书籍:Android 开发艺术探索

IPC机制1的更多相关文章

  1. Anciroid的IPC机制-Binder概述

    在Linux系统中,是以进程为单位分配和管理资源的.出于保护机制,一个进程不能直接访问另一个进程的资源,也就是说,进程之间互相封闭.但是,在一个复杂的应用系统中,通常会使用多个相关的进程来共同完成一项 ...

  2. Handler消息机制与Binder IPC机制完全解析

    1.Handler消息机制 序列 文章 0 Android消息机制-Handler(framework篇) 1 Android消息机制-Handler(native篇) 2 Android消息机制-H ...

  3. ndk学习15: IPC机制

    Linux IPC机制 来自为知笔记(Wiz)

  4. Android之IPC机制

    Android IPC简介 任何一个操作系统都需要有相应的IPC机制,Linux上可以通过命名通道.共享内存.信号量等来进行进程间通信.Android系统不仅可以使用了Binder机制来实现IPC,还 ...

  5. IPC机制--Binder

    文章来自 Android技术内幕 系统卷 转:http://www.linuxidc.com/Linux/2011-08/40508.htm 什么是IPC机制以及IPC机制的种类 在Linux中,是以 ...

  6. IPC机制

    转:http://blog.chinaunix.net/uid-26125381-id-3206237.html  IPC 三种通信机制 2012-05-13 17:23:55 最近看了,IPC三种通 ...

  7. IPC 机制简介

    IPC 机制简介 概述 在Unix早期发展中,做出重大贡献的两大主力Bell实验室和伯克利大学(BSD)在IPC(InterProcess Communication)方面的侧重点有所不同.前者对Un ...

  8. pipe()管道最基本的IPC机制

    <h4>进程间通信 fork pipe pie_t 等用法(管道机制 通信)</h4>每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之 ...

  9. Android的IPC机制(一)——AIDL的使用

    综述 IPC(interprocess communication)是指进程间通信,也就是在两个进程间进行数据交互.不同的操作系统都有他们自己的一套IPC机制.例如在Linux操作系统中可以通过管道. ...

  10. [置顶] 深入理解android之IPC机制与Binder框架

    [android之IPC机制与Binder框架] [Binder框架.Parcel.Proxy-Stub以及AIDL] Abstract [每个平台都会有自己一套跨进程的IPC机制,让不同进程里的两个 ...

随机推荐

  1. 微信小程序支付以及微信退款开发

    最近公司项目急着测试,需要开发微信小程序+微信支付+微信退款,本着这几天的一些研究,决定记录一下开发的过程. 本着知识分享的原则,希望对大家有所帮助. 本篇针对的是微信小程序的支付开发,如果有对微信公 ...

  2. C++学习书籍推荐《The C++ Standard Library 2nd》下载

    百度云及其他网盘下载地址:点我 编辑推荐 经典C++教程十年新版再现,众多C++高手和读者好评如潮 畅销全球.经久不衰的C++ STL鸿篇巨著 C++程序员案头必 备的STL参考手册 全面涵盖C++1 ...

  3. jdk源码--LinkedList

    本文基于jdk1.8_171 LinkedList介绍 之前看了ArrayList,内部是一个数组.这次看了LinkedList,作用和ArrayList一样,但是内部是链表形式.链表结构如下图: 数 ...

  4. free()函数释放一段分配的内存之陷阱

    朋友们对malloc函数应该是比较熟悉了,此函数功能是分配一段内存地址,并且将内存地址给一个指针变量,最后记得再调用free函数释放这段内存地址就可以了,标准的流程对吧,好像没什么问题.但是按照此标准 ...

  5. CF1194D 1-2-K Game (博弈论)

    CF1194D 1-2-K Game 一道简单的博弈论题 首先让我们考虑没有k的情况: 1. (n mod 3 =0) 因为n可以被分解成若干个3相加 而每个3可以被分解为1+2或2+1 所以无论A出 ...

  6. python函数知识三 函数名的使用、格式化、递归

    12.函数名的使用 函数是第一类对象 函数名可以当做值被赋值给变量 def func(): print(1) return a = func print(func) print(a) a() 函数名可 ...

  7. 【译】深入理解G1的GC日志(一)

    本文翻译自:https://www.redhat.com/en/blog/collecting-and-reading-g1-garbage-collector-logs-part-2?source= ...

  8. UVA11988 【Broken Keyboard (a.k.a. Beiju Text)】:题解

    题目链接:https://www.luogu.org/problemnew/show/UVA11988 这题虽说是和链表有关的模拟,但其实并不是很需要啊,但蒟蒻用了(说的好听是练手,说的难听是太弱), ...

  9. 端口,OSI7层模型,TCP的三次握手和四次挥手,进度条

    1.端口: 端口是为了将同一个电脑上的不同程序进行隔离 IP是找电脑,端口是找电脑上的程序 MySQL是一个软件,帮助我们在硬盘上进行文件操作,默认端口是3306 Redis是一个软件,帮助我们在内存 ...

  10. 我狠起来连自己都打---如何简单实现Azure resource自动打标签

    你是否还在为花费大量Azure Resource打标签而烦恼呢?你是否还在因为这样低效的重复劳动而痛苦呢? 在很长一段时间内,笔者既要做云架构调整,又要做日常系统维护,还要参与各种各样的项目,在这种情 ...