关于IPC,Binder,AIDL,Intent

很多时候大家会同时提到IPC、Binder、AIDL这几个概念,但对于它们之间的关系可能没有一个清晰的认识。还有Intent与它们有什么关系呢?

概述

首先看看各自的全称与中文名:

  • IPC:Inter-Process Communication(进程间通信)
  • Binder:Binder进程间通信机制
  • AIDL:Android Interface Definition Language(android接口定义语言)
  • Intent:意图

再来看一张关系示意图:

这里写图片描述

图中最里层是Android系统匿名共享内存Ashmem(Anonymous Shared Memory),其作用之一即通过Binder进程间通信机制来实现进程间的内存共享。

通过示意图其实已经能知道个大概:
IPC是一种概念,即进程间通信;其它几个都是Android里的概念;Binder是IPC的一种具体实现;AIDL是Binder机制向外提供的接口,目的就是为了方便对Binder的使用;Intent是最高层级的封装,实质是封装了对Binder的使用,当然Intent也常常在同一进程中调用,只是把两种方式封装在一起了。

为什么搞这么复杂呢,目的还是为了最大发挥系统效率与方便开发者使用。

IPC

IPC是操作系统层面的概念,因为进程是操作系统里最基本的单位,进程的一大特征就是有自己独立的内存地址空间,所以同一进程里的代码能直接访问其地址空间的内存,而其它进程是不能直接访问的。操作系统是多进程的,多个进程配合工作肯定会涉及到互相的通信,故出现了IPC。而对IPC的实现也不只一种,有很多,且有各自的长处,比如Socket就是一种IPC,其长处就是能跨机器进行进程间通信。

Android系统的本质上其实是Linux系统,可以看成是在Linux内核上运行着一个超级程序。虽然Linux本身提供了很多IPC机制,但是Android主要是运行在手机上了,为了能更好的适应手机这个环境同时简化开发,Binder机制出现了。而Binder本质上是通过共享内存来实现的IPC( 直白点就是一段物理内存在不同进程中都映射了虚拟地址,虚拟地址可能不同,一个对它写,另一个对它读,然后解析、处理),但是Binder机制不是简简单单共享内存,而是搭了一套巧妙的架构,来达到最终共享内存进行IPC的目的。

Binder

Binder机制具体的实现涉及到很多C/C++的代码,我们了解一下其思想就行了。Binder通信采用的是client-server通信结构,client与server的通信由Binder驱动程序和Service Manager组件协助,这两个组件Android已经实现好了并由系统运行,而开发者只需要按照框架规范实现client与server接口即可。这里可以参考我总结的对Binder的概述Binder进程间通信机制概述(Android系统源代码情景分析学习笔记)

更进一步地了解可以参考我之前转载的一篇文章Android Binder设计与实现 - 设计篇(强烈推荐) 。

最后如果还要深入了解源码可以参考罗升阳的博客或者他写的书《Android系统源代码情景分析》。

AIDL

AIDL是为了方便使用Binder框架搞的一个东西,其实不用它也能达到目的,但是用AIDL就简化了操作。只要按照规范写一个.aidl文件,编译器就会帮助我们自动创建一个与interface同名的.java文件,里面已经帮我们自动实现了一个Binder,这些标准化的东西,用模板自动生成即可,可以让开发者尽量关注功能实现上。

例如:

AIDL文件:

interface IMyAidl {
   int add(int num1,int num2);

   List<Dog> addDog(in Dog dog);
}

编译器根据AIDL文件生成的Java文件:

public interface IMyAidl extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.aidl.tsnt.server.IMyAidl {
        private static final java.lang.String DESCRIPTOR = "com.aidl.tsnt.server.IMyAidl";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.aidl.tsnt.server.IMyAidl interface,
         * generating a proxy if needed.
         */
        public static com.aidl.tsnt.server.IMyAidl asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.aidl.tsnt.server.IMyAidl))) {
                return ((com.aidl.tsnt.server.IMyAidl) iin);
            }
            return new com.aidl.tsnt.server.IMyAidl.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_add: {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.add(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
                case TRANSACTION_addDog: {
                    data.enforceInterface(DESCRIPTOR);
                    com.aidl.tsnt.server.Dog _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.aidl.tsnt.server.Dog.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    java.util.List<com.aidl.tsnt.server.Dog> _result = this.addDog(_arg0);
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.aidl.tsnt.server.IMyAidl {
            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 int add(int num1, int num2) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(num1);
                    _data.writeInt(num2);
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public java.util.List<com.aidl.tsnt.server.Dog> addDog(com.aidl.tsnt.server.Dog dog) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.aidl.tsnt.server.Dog> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((dog != null)) {
                        _data.writeInt(1);
                        dog.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addDog, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.aidl.tsnt.server.Dog.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_addDog = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    public int add(int num1, int num2) throws android.os.RemoteException;

    public java.util.List<com.aidl.tsnt.server.Dog> addDog(com.aidl.tsnt.server.Dog dog) throws android.os.RemoteException;
}

关于使用AIDL,可以参考AIDL最佳实践

Intent

Intent进行进程间通信比较常见,比如打开另一个应用的Activity、发送广播等。

Intent的架构包括三方面:

  • Client,发送这个Intent的activity;
  • Server,ActivityManagerService,它主要是负责分发这些Intent给适当的对象;
  • Target,也就是那些需要处理这个Intent的activity,称为Receiver。

而进程间发送消息或者broadcast,并不是直接把intent发过去,而是把intent打包到Parcel中,通过binder机制传递消息。

参考:IPC、Binder、AIDL与Intent之间区别与联系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值