精华内容
下载资源
问答
  • Android Binder机制

    2018-02-26 15:55:18
    Android Binder机制 总共11篇博客。详细介绍BINDER的内部机制
  • Android Binder 机制

    2019-01-27 20:09:01
    Android Binder机制的文章非常多,这篇文章主要是理一下我对Binder的理解。本文不是一篇介绍Binder的文章,也不是一篇探讨Binder实现的文章。 本文会以AndroidStudio根据aidl接口自动产生的java文件来看Binder,进而...

    Android Binder机制的文章非常多,这篇文章主要是理一下我对Binder的理解。本文不是一篇介绍Binder的文章,也不是一篇探讨Binder实现的文章。
    本文会以AndroidStudio根据aidl接口自动产生的java文件来看Binder,进而来理解Binder机制

    其实Android的Binder机制类似于:RPC(远程过程调用)。如果你理解它,相信Binder机制就更容易理解了。

    首先我们使用AndroidStudio来定义一个aidl接口:

    interface IUserManager {
        int getUserAge(in String userName);
    }
    

    然后我们来直接看一个由AndroidStudio根据自定义的aidl接口IUserManager产生的IUserManager.java文件。

    这个文件我们来分3个部分看:

    IUserManager接口结构

    public interface IUserManager extends android.os.IInterface {
    
        public static abstract class Stub extends android.os.Binder implements com.susion.demo.aidl.IUserManager {..}
    
        public int getUserAge(java.lang.String userName) throws android.os.RemoteException;
    }
    

    这个接口的结构还是很简单的:

    1. 它继承自android.os.IInterface
    2. 定义了一个待实现的方法int getUserAge()
    3. 定义了一个Stub类。这个类继承自Binder,并实现了IUserManager接口。

    int getUserAge()这个方法就是我们IUserManager接口的方法。而android.os.IInterface是什么呢?先看一下它在源码中的定义:

    /**
     * Base class for Binder interfaces.  When defining a new interface,
     * you must derive it from IInterface.
     */
    public interface IInterface
    {
        /**
         * Retrieve the Binder object associated with this interface.
         * You must use this instead of a plain cast, so that proxy objects
         * can return the correct result.
         */
        public IBinder asBinder(); //IBinder是Binder的抽象接口
    }
    

    即他是所有Binder都要实现的接口, 为什么呢?举一个我们都熟悉的场景 :

    比如ApplicationThreadActivityManagerService(运行在服务端进程)就可以通过它来调用我们客户端的方法。我们会把这些方法抽象为一个接口(IApplicationThread),这个接口可以理解为我们告诉服务端,你可以对客户端执行哪些操作。

    我们还知道ApplicationThread其实他就是一个Binder。所以这两者一结合就可以这么说ApplicationThread: 客户端提供给服务端一个Binder,通过这个Binder服务端可以对客户端做一些操作,这些操作具体定义在IApplicationThread接口中。

    我们称IApplicationThreadApplicationThread这个Binder的功能。 所以Binder除了可以理解为系统给我们提供的一个跨进程通信的对象。 我们在用Binder通信时,还可以说Binder是一个具有某些功能的一个对象。

    那么怎么表示Binder有功能呢? 即要继承IInterfaceIInterface可以表示Binder有功能, 不然你想一个,那么多Binder都只实现自己的接口, 那么系统层就不好操作了,它总不能向下强转为Binder吧,所以Android定义了一个更高层级的接口IInterface。描述Binder功能的接口必须继承自这个接口。

    重点: Binder、Binder的功能(IApplicationThread)、IInterface它们都在同一个对象上 -> ApplicationThread

    Stub

    它是IUserManager的内部静态类,看一下它的具体声明:

    static abstract class Stub extends android.os.Binder implements com.susion.demo.aidl.IUserManager 
    

    即它是一个Binder,可以用来跨进程通信。它具有IUserManager定义的功能。

    看一下它的具体结构:

        public static abstract class Stub extends android.os.Binder implements com.susion.demo.aidl.IUserManager {
    
            private static final java.lang.String DESCRIPTOR = "com.susion.demo.aidl.IUserManager";
    
            static final int TRANSACTION_userCount = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    
            public Stub() {
                this.attachInterface(this, DESCRIPTOR);
            }
    
            public static com.susion.demo.aidl.IUserManager asInterface(android.os.IBinder obj) {
                if ((obj == null)) {
                    return null;
                }
                android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
                if (((iin != null) && (iin instanceof com.susion.demo.aidl.IUserManager))) {
                    return ((com.susion.demo.aidl.IUserManager) iin);
                }
                return new com.susion.demo.aidl.IUserManager.Stub.Proxy(obj);
            }
    
            @Override
            public android.os.IBinder asBinder() {retun this;}
    
            @Override
            public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {...}
    
            private static class Proxy implements com.susion.demo.aidl.IUserManager {...}
    
        }
    

    我们还是一个一个的看一下:

    DESCRIPTOR

    基于我们前面的解释,我们知道在跨进程通信中Binder对象具有某种功能->IInterface。但是Binder通信机制中那么多Binder都有IInterface。那么系统怎么识别哪个Binder是哪个Binder呢?所以IInterface只是一个能力的抽象,DESCRIPTOR就是来表示具体是哪一个功能IInterface

    TRANSACTION_userCount

    即功能下的哪个操作。

    Stub构造函数

        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }
    

    即一个Stub(Binder)在构造的时候,就标识好了自己的具体功能IInterface(IUserManager)。来看一下attachInterface(this, DESCRIPTOR)做了什么:

    //Binder.java
    public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
        mOwner = owner;  
        mDescriptor = descriptor;
    }
    

    即,Binder在内部会用IInterface来保存自己的功能。和这个功能更对应的唯一描述descriptor,方便在通信的时候寻找。

    asBinder()

    自己返回自己,因为自己本身就是个Binder呀。

    onTransact()

    当其他进程想跨进程调用我这个Binder的功能时,必须通过这个方法来沟通。这个方法我们最后再来看。

    asInterface(android.os.IBinder obj)

    即接收一个IBinder(这个IBinder是系统传入的), 把这个IBinder转化为它所具有功能接口。其实这里就是Binder跨进程通信的一个核心 。那怎么转化的呢?

    • 调用者和Binder对象位于同一个进程

    那么系统就会直接传给你在这个进程创建的Stub(Binder)。所以 obj.queryLocalInterface(DESCRIPTOR):

    public  IInterface queryLocalInterface(String descriptor) {
        if (mDescriptor.equals(descriptor)) {
            return mOwner;
        }
        return null;
    }
    

    即如果参数descriptor和这个Binder的功能唯一描述相同。就会返回Binder的功能mOwner

    • 调用者和Binder对象不在同一个进程

    这时系统实际传的是一个BinderProxy, 你可以理解为它是另一个进程中的Binder的替身。我们就可以把它当成另一个进程的Binder。我们看一下BinderProxyqueryLocalInterface()方法:

    /**
    * Retrieve a local interface - always null in case of a proxy
    */
    public IInterface queryLocalInterface(String descriptor) {
        return null;
    }
    

    所以此时asInterface()返回的是: IUserManager.Stub.Proxy(obj), 即代理对象,它代理了BinderProxy

    IUserManager.Stub.Proxy

    它是Stub的静态内部类,如果调用者和Binder不在同一个进程的话,调用者拿到的实际是它:

        private static class Proxy implements com.didi.virtualapk.demo.aidl.IUserManager {
            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 getUserAge(java.lang.String userName) 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.writeString(userName);
                    mRemote.transact(Stub.TRANSACTION_getUserAge, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }
    

    我们前面说了它其实是BinderProxy的代理。为什么要对BinderProxy加这个代理呢?看一下getUserAge():

        public int getUserAge(java.lang.String userName) 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.writeString(userName);
                mRemote.transact(Stub.TRANSACTION_getUserAge, _data, _reply, 0);
                _reply.readException();
                _result = _reply.readInt();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }
    

    即是调用mRemote.transact()(BinderProxy的)方法。Stub.TRANSACTION_getUserAge是要调用的远程Binder方法的getUserAge()对应的描述符。

    _data是序列化后的入参、_reply是序列化后的返回值。可以看到_data所携带的参数是需要序列化的,_reply所带的内容是被序列化的,所以读取要反序列化。

    所以IUserManager.Stub.Proxy类的作用就是在跨进程调用时对传给mRemote(BinderProxy)的参数做序列化,对mRemote(BinderProxy)返回值做反序列化。参数的接受者和返回者是BinderProxy

    具体调用Binder的能力是使用BinderProxytransact()方法,它是跨进程通信的核心 , 我们来看一下这个方法:

    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        ...
        return transactNative(code, data, reply, flags); // native 方法
    }
    

    省略了不重要的代码。即BinderProxy是通过transactNative来与远程Binder跨进程通信的。具体怎么实现,这里就不追究了。

    Stub.onTransact()

    我们前面没有看这个方法,这里我们来看一下:

    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_getUserAge: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                int _result = this.getUserAge(_arg0);
                reply.writeNoException();
                reply.writeInt(_result);
                return true;
            }
        }
        return super.onTransact(code, data, reply, flags);
    }
    

    根据IUserManager.Stub.Proxy我们知道,如果不在同一个进程,那么参数是被序列化后传过来的,所以这个方法是用来对入参做反序列化,并对返回值做序列化的

    最后我们用一张图来总结Binder进程通信机制 :

     

     

    +qq群:853967238。获取以上高清技术思维图,以及相关技术的免费视频学习资料。

    展开全文
  • AndroidBinder机制

    2017-04-25 23:37:41
    Android Binder Android中为了保护操作系统中进程互不干扰设计了进程隔离机制,这个技术是为了防止进程A写入进程B的情况发生。进程隔离的实现,使用了虚拟地址空间,进程A的虚拟地址和进程B的虚拟地址不同,这样就...

    Android Binder


    自己写的一个进程间通信例子https://github.com/dechaow/AIDLDemo



    Android中为了保护操作系统中进程互不干扰设计了进程隔离机制,这个技术是为了防止进程A写入进程B的情况发生。进程隔离的实现,使用了虚拟地址空间,进程A的虚拟地址和进程B的虚拟地址不同,这样就防止进程A将数据信息写入进程B


    虚拟地址和物理地址是一种映射关系,程序中使用的都是虚拟地址


    Linux系统内存分为两个部分:内核空间和用户空间。内核空间是内核(即操作系统的核心)执行(即运行)并提供其服务的位置


    用户空间是用户进程(即除内核以外的一切)运行的那组内存位置。进程是程序的执行示例,内核的一个角色是管理此空间内的各个用户进程,并防止它们彼此干扰


    Linux Kernel是操作系统的核心,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限


    用户进程只能通过使用系统调用来访问内核空间。系统调用是类似Unix的操作系统中由内核执行的服务的活动的请求。


    Kernel space can be accessed by user processes only through the use of system calls.


    Linux的7种运行级别:


    运行级别0:系统停机状态,系统默认运行级别不能设为0,否则不能正常   启动


    运行级别1:单用户工作态,root权限,用于系统维护,机制远程登录


    运行级别2:多用户运行态(没有NFS)


    NFS:Network File System 网络文件系统


    运行级别3:完全的用户状态(有NFS),登录后进入控制台命令行模式


    运行级别4:系统未使用,保留


    运行级别5:X11控制台,登录后进入图形GUI模式


    运行级别6:系统正常关闭并重启,默认运行级别不能设为6,否则不能正常启动




    当一个任务执行系统调用而陷入内核代码中执行时,我们就成进程处于内核运行态(简称为内核态)此时处理器处于特权级最高的(0级)内核代码中执行。当进程在执行用户自己的代码时,则称其处于运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。处理器在特权等级高的时候才能执行那些特权CPU命令


    用户空间与用户空间进行通信:操作系统内核添加支持,传统的Linux通信机制有(Socket、管道、System V、共享内存);Android中是Binder


    Linux的动态可加载内核模块(Loadable Kernel Module,LKM)机制:模块是具有独立功能的程序,它可以单独被编译,但不能独立运行,它在运行时被连接到内核作为内核的一部分在内核空间运行。这样Android系统可以通过一个内核模块运行在内核空间,用户进程之间通过这个模块作为桥梁,就可以进行通信了。


    在Android中,这个运行在内核空间的,负责各个用户进程通过Binder通信的内核模块叫做Binder驱动


    驱动程序一般指的是设备驱动程序(Diver Diver),是一种可以使计算机和设备通信的特殊程序,相当于硬件的接口,操作系统只有通过这个接口,才能控制硬件设备的工作。


    驱动就是操作硬件的接口,为了支持Binder通信过程,Binder使用了一种“硬件”,因此这个模块被称之为驱动


    Binder的优点(性能和安全方面):Binder相对于传统的Socket方式,更加高效,另外传统的通信方式对于双方的身份并没有做出严格的验证,只有在上层协议上进行架设,而Binder机制从协议本身就支持对通信双方进行身份校验,Android为每个应用程序都分配了自己的UID来作为鉴别进程身份的重要标志。大大的提升了安全性。传统的IPC只能由用户在数据包里填入UID和PID,不够可靠。


    Binder基于Client-Server通信模型,传输只需要一次拷贝,为发送方添加UID/PID身份,既支持实名Binder又支持匿名Binder,安全性高。


    Binder通信模型:


    Client Server ServiceManager Binder驱动


    做一个打电话的比喻,如果A要给B打电话,首先要有B的电话号码,而电话号码存在通讯录里面,这里的ServiceManager就相当于通讯录,但是只有电话号码还是不能打通的,还需要有基站,Binder在这里就相当于是基站的性质


    整个完整的步骤如下:


    1 ServiceManager的建立,首先,有一个进程向驱动提出申请为ServiceManager,驱动同意后,ServiceManager进程负责管理Service。ServiceManager的注册方式也是通过Binder机制来进行的,只不过它比较特殊,当一个进程使用用BINDER_SET_CONTEXT_MGR命令将自己注册成ServiceManager时Binder驱动会自动为它创建Binder实体,这个进程就是的ServiceManager,然后ServiceManager充当Server,其他进程都是Client


    2 各个Server向ServiceManager注册,每个Server端进程启动之后,向ServiceManager进行注册自己的名字和返回对应的地址,然后这时候ServiceManager就存了很多进程的名字和地址,如果想要通信需要调用ServiceManager查询对应的地址


    3 Client和Server想要通信,首先询问ServiceManager,然后查询后返回地址,就可以和Server进行通信了。


    Binder驱动在这里起着最重要的关系


    Binder跨进程原理:


    用户空间想要操作内核空间,需要通过两个系统调用:copy_from_user,copy_to_user.


    假设Client想要调用Server的object对象的add方法:


    首先Server向ServiceManager注册,然后Client向ServiceManager查询这个Server,我们知道,进程间的通信都会经过运行在内核里面的驱动,驱动在数据流过的时候做了一点手脚,它并不会返回一个真正的object对象而是一个objectProxy,这objectProxy也有一个add方法,但是这并不是真正的object对象,objectProxy做的事情就是把参数包装然后交给驱动。
    但是Client进程并不知道这个对象并不是真正的object对象,然后就当作是真的object对象调用它的add方法,然后这个add方法就会发消息给驱动,驱动收到消息发现是objectProxy的方法,就知道这个Client想要调用的是Server的object对象,然后驱动就会通知Server,调用你的object对象的add方法,然后把结果返回给我,然后Server进程收到这个消息,照做之后将结果返回给驱动,驱动然后把结果返回给Client进程。整个过程就完成了。


    由于objectProxy与Server进程里面原始的object如此相似,给我们的感觉就是直接将Server中的object对象传递到了Client进程,所以,我们可以说Binder对象是可以进行跨进程传递的对象。但是其实这里用的是代理模式。


    实际上。由于我们Server向ServiceManager注册时也是跨进程通信,驱动当然也会对这个过程进行暗箱操作。ServiceManager端存在的Server对象其实也是代理对象。后面Client向ServiceManager查询的时候,驱动会给Client返回另外一个代理对象。Server进程的本地对象只会有一个,其他进程所拥有的都是它的代理。


    Binder到底是什么:


    Binder的设计采用了面向对象的思想,在Binder通信模型的四个角色里。它们的代表都是“Binder”,这样对于Binder通信的使用者而言,Server里面的Binder和Client里面的Binder没有什么不同,一个BInder对象就代表了所有,它不用关心实现的细节。甚至不用关心驱动以及ServiceManager的存在,这就是抽象。


    通常我们说的Binder指的是一种通信机制,我们说AIDl使用Binder进行通信,指的就是Binder这种IPC机制


    对于Server进程来说,Binder指的是Binder本地对象。


    对于Client来说,Binder指的是代理对象。


    对于传输过程而言,Binder是可以进行跨进程传递的对象。


    驱动里面的Binder


    在驱动中,Binder本地对象的代表是一个binder_node的数据结构,Binder代理对象是binder_ref代表的,有的地方把Binder本地对象直接称作Binder实体,把Binder的代理对象称作为Binder引用,其实就是说的是Binder对象在驱动里面的表现形式








    展开全文
  • Android Binder 机制学习总结 Android Binder 机制学习总结
  • android binder机制

    2010-08-24 21:00:00
     android binder机制            http://wallage.blog.163.com/blog/static/17389624201031411019444/<br />第一部分Binder的组成 1.1 驱动程序部分

     

    android binder机制                                       

                    
                                                                  

    http://wallage.blog.163.com/blog/static/17389624201031411019444/

    第一部分Binder的组成

    1.1 驱动程序部分驱动程序的部分在以下的文件夹中:

    kernel/include/linux/binder.h

    kernel/drivers/android/binder.c

        binder驱动程序是一个miscdevice,主设备号为10,此设备号使用动态获得(MISC_DYNAMIC_MINOR),其设备的节点为:

    /dev/binder

        binder驱动程序会在proc文件系统中建立自己的信息,其文件夹为/proc/binde,其中包含如下内容:

    proc目录:调用Binder各个进程的内容

    state文件:使用函数binder_read_proc_state

    stats文件:使用函数binder_read_proc_stats

    transactions文件:使用函数 binder_read_proc_transactions

    transaction_log 文件:使用函数binder_read_proc_transaction_log,其参数为binder_transaction_log (类型为struct binder_transaction_log)

    failed_transaction_log 文件:使用函数binder_read_proc_transaction_log 其参数为

    binder_transaction_log_failed (类型为struct binder_transaction_log)

        在binder文件被打开后,其私有数据(private_data)的类型:

    struct binder_proc

        在这个数据结构中,主要包含了当前进程、进程ID、内存映射信息、Binder的统计信息和线程信息等。

        在用户空间对Binder驱动程序进行控制主要使用的接口是mmap、poll和ioctl,ioctl主要使用的ID为:

    #define BINDER_WRITE_READ        _IOWR('b', 1, struct binder_write_read)

    #define BINDER_SET_IDLE_TIMEOUT  _IOW('b', 3, int64_t)

    #define BINDER_SET_MAX_THREADS   _IOW('b', 5, size_t)

    #define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, int)

    #define BINDER_SET_CONTEXT_MGR   _IOW('b', 7, int)

    #define BINDER_THREAD_EXIT       _IOW('b', 8, int)

    #define BINDER_VERSION           _IOWR('b', 9, struct binder_version)

        BR_XXX等宏为BinderDriverReturnProtocol,表示Binder驱动返回协议。

        BC_XXX等宏为BinderDriverCommandProtocol,表示Binder驱动命令协议。

        binder_thread是Binder驱动程序中使用的另外一个重要的数据结构,数据结构的定义如下所示:

    struct binder_thread {

          struct binder_proc *proc;

         struct rb_node rb_node;

         int pid;

         int looper;

         struct binder_transaction *transaction_stack;

         struct list_head todo;

         uint32_t return_error;

         uint32_t return_error2;

         wait_queue_head_t wait;

         struct binder_stats stats;

    };

        binder_thread 的各个成员信息是从rb_node中得出。

        BINDER_WRITE_READ是最重要的ioctl,它使用一个数据结构binder_write_read定义读写的数据。

    struct binder_write_read {

         signed long write_size;

         signed long write_consumed;

         unsigned long write_buffer;

         signed long read_size;

         signed long read_consumed;

         unsigned long read_buffer;

    };

     

      1.3 binder的库的部分

        binder相关的文件作为Android的uitls库的一部分,这个库编译后的名称为libutils.so,是Android系统中的一个公共库。

        主要文件的路径如下所示:

    frameworks/base/include/utils/*

    frameworks/base/libs/utils/*

     

        主要的类为:

      RefBase.h :

        引用计数,定义类RefBase。

      Parcel.h :

        为在IPC中传输的数据定义容器,定义类Parcel

       IBinder.h:

        Binder对象的抽象接口, 定义类IBinder

      Binder.h:

        Binder对象的基本功能, 定义类Binder和BpRefBase

      BpBinder.h:

      BpBinder的功能,定义类BpBinder

       IInterface.h:

      为抽象经过Binder的接口定义通用类,

        定义类IInterface,类模板BnInterface,类模板BpInterface

      ProcessState.h

        表示进程状态的类,定义类ProcessState

       IPCThreadState.h

        表示IPC线程的状态,定义类IPCThreadState

    各个类之间的关系如下所示:

     android binder机制 (转载) - Wallace Wang - 
懒羊羊的南瓜屋

     

            1.2 servicemanager部分        servicemanager是一个守护进程,用于这个进程的和/dev/binder通讯,从而达到管理系统中各个服务的作用。

            可执行程序的路径:

            /system/bin/servicemanager        

    开源版本文件的路径:

    frameworks/base/cmds/servicemanager/binder.h

    frameworks/base/cmds/servicemanager/binder.c

    frameworks/base/cmds/servicemanager/service_manager.c

           程序执行的流程:

    open():打开binder驱动

    mmap():映射一个 128*1024字节的内存

    ioctl(BINDER_SET_CONTEXT_MGR):设置上下文为mgr

           进入主循环binder_loop()

                 ioctl(BINDER_WRITE_READ),读取

                           binder_parse()进入binder处理过程循环处理

             binder_parse()的处理,调用返回值:

            当处理BR_TRANSACTION的时候,调用svcmgr_handler()处理增加服务、检查服务等工作。各种服务存放在一个链表(svclist)中。其中调用binder_等开头的函数,又会调用ioctl的各种命令。

            处理BR_REPLY的时候,填充binder_io类型的数据结构

     

      第二部分 Binder的运作

      2.1 Binder的工作机制

          Service Manager是一个守护进程,它负责启动各个进程之间的服务,对于相关的两个需要通讯的进程,它们通过调用libutil.so库实现通讯,而真正通讯的机制,是内核空间中的一块共享内存。

           android 
binder机制 (转载) - Wallace Wang - 懒羊羊的南瓜屋

      2.2 从应  用程序的角度看Binder

      从应用程序的角度看Binder一共有三个方面:

      Native 本地:例如BnABC,这是一个需要被继承和实现的类。

      Proxy 代理:例如BpABC,这是一个在接口框架中被实现,但是在接口中没有体现的类。

      客户端:例如客户端得到一个接口ABC,在调用的时候实际上被调用的是BpABC

    android binder机制 (转载) - Wallace Wang - 
懒羊羊的南瓜屋

    本地功能(Bn)部分做的:

        实现BnABC:: BnTransact()

        注册服务:IServiceManager::AddService

    代理部分(Bp)做的:

        实现几个功能函数,调用BpABC::remote()->transact()

    客户端做的:

        获得ABC接口,然后调用接口(实际上调用了BpABC,继而通过IPC调用了BnABC,然后调用了具体的功能)

     

           在程序的实现过程中BnABC和BpABC是双继承了接口ABC。一般来说BpABC是一个实现类,这个实现类不需要在接口中体现,它实际上负责的只是通讯功能,不执行具体的功能;BnABC则是一个接口类,需要一个真正工作的类来继承、实现它,这个类才是真正执行具体功能的类。

           在客户端中,从ISeriviceManager中获得一个ABC的接口,客户端调用这个接口,实际上是在调用BpABC,而BpABC又通过 Binder的IPC机制和BnABC通讯,BnABC的实现类在后面执行。

      事实上,服务器的具体实现和客户端是两个不同的进程,如果不考虑进程间通讯的过程,从调用者的角度,似乎客户端在直接调用另外一个进程间的函数——当然这个函数必须是接口ABC中定义的。

      2.3 ISericeManager的作用

          ISericeManager涉及的两个文件是ISericeManager.h和ISericeManager.cpp。这两个文件基本上是 ISericeManager。ISericeManager是系统最先被启动的服务。非常值得注意的是:ISericeManager本地功能并没有使现,它实际上由ServiceManager守护进程执行,而用户程序通过调用BpServiceManager来获得其他的服务。

          在ISericeManager.h中定义了一个接口,用于得到默认的ISericeManager:

            sp<IServiceManager> defaultServiceManager();

         这时得到的ISericeManager实际上是一个全局的ISericeManager。 

     

      第三部分 程序中Binder的具体实现

       3.1 一个利用接口的具体实现

        PermissionController也是libutils中定义的一个有关权限控制的接口,它一共包含两个文件:IPermissionController.h和IPermissionController.cpp这个结构在所有类的实现中都是类似的。

         头文件IPermissionController.h的主要内容是定义IPermissionController接口和类 BnPermissionController:

    class IPermissionController : public IInterface

    {

    public:

        DECLARE_META_INTERFACE(PermissionController);

        virtual bool   checkPermission(const String16& permission,int32_t pid, int32_t uid) = 0;

        enum {

            CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION

        };

    };

    class BnPermissionController : public BnInterface<IPermissionController>

    {

    public:

        virtual status_t    onTransact( uint32_t code,

                                        const Parcel& data,

                                        Parcel* reply,

                                        uint32_t flags = 0);

    };

        IPermissionController是一个接口类,只有checkPermission()一个纯虚函数。

        BnPermissionController继承了以BnPermissionController实例化模版类BnInterface。因此,BnPermissionController,事实上BnPermissionController双继承了BBinder和 IPermissionController。

        实现文件IPermissionController.cpp中,首先实现了一个BpPermissionController。

    class BpPermissionController : public BpInterface<IPermissionController>

    {

    public:

        BpPermissionController(const sp<IBinder>& impl)

            : BpInterface<IPermissionController>(impl)

        {

        }

        virtual bool checkPermission(const String16& permission, int32_t pid, int32_t uid)

        {

            Parcel data, reply;

            data.writeInterfaceToken(IPermissionController::

                                           getInterfaceDescriptor());

            data.writeString16(permission);

            data.writeInt32(pid);

            data.writeInt32(uid);

            remote()->transact(CHECK_PERMISSION_TRANSACTION, data, &reply);

            if (reply.readInt32() != 0) return 0;

            return reply.readInt32() != 0;

        }

    };

    IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController");

        BpPermissionController继承了BpInterface<IPermissionController>,它本身是一个已经实现的类,而且并没有在接口中体现。这个类按照格式写就可以,在实现checkPermission()函数的过程中,使用Parcel作为传输数据的容器,传输中时候transact()函数,其参数需要包含枚举值CHECK_PERMISSION_TRANSACTION。 IMPLEMENT_META_INTERFACE用于扶助生成。

        BnPermissionController中实现的onTransact()函数如下所示:

    status_t BnPermissionController:: BnTransact(

        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

    {

        switch(code) {

            case CHECK_PERMISSION_TRANSACTION: {

                CHECK_INTERFACE(IPermissionController, data, reply);

                String16 permission = data.readString16();

                int32_t pid = data.readInt32();

                int32_t uid = data.readInt32();

                bool res = checkPermission(permission, pid, uid);

                reply->writeInt32(0);

                reply->writeInt32(res ? 1 : 0);

                return NO_ERROR;

            } break;

            default:

                return BBinder:: BnTransact(code, data, reply, flags);

        }

    }

           在onTransact() 函数中根据枚举值判断数据使用的方式。注意,由于BnPermissionController也是继承了类 IPermissionController,但是纯虚函数checkPermission()依然没有实现。因此这个 BnPermissionController类并不能实例化,它其实也还是一个接口,需要一个实现类来继承它,那才是实现具体功能的类。

      3.2 BnABC的实现

        本地服务启动后将形成一个守护进程,具体的本地服务是由一个实现类继承BnABC来实现的,这个服务的名称通常叫做ABC。

        在其中,通常包含了一个instantiate()函数,这个函数一般按照如下的方式实现:

    void ABC::instantiate() {

        defaultServiceManager()->addService(

                String16("XXX.ABC"), new ABC ());

    }

        按照这种方式,通过调用defaultServiceManager()函数,将增加一个名为"XXX.ABC"的服务。

        在这个defaultServiceManager()函数中调用了:

    ProcessState::self()->getContextObject(NULL));

        IPCThreadState* ipc = IPCThreadState::self();

       IPCThreadState::talkWithDriver()

    在ProcessState 类建立的过程中调用open_driver()打开驱动程序,在talkWithDriver()的执行过程中。

      3.3 BpABC调用的实现

        BpABC调用的过程主要通过mRemote()->transact() 来传输数据,mRemote()是BpRefBase的成员,它是一个IBinder。这个调用过程如下所示:

        mRemote()->transact()

        Process::self()

        IPCThreadState::self()->transact()

        writeTransactionData()

        waitForResponse()

        talkWithDriver()

        ioctl(fd, BINDER_WRITE_READ, &bwr)

        在IPCThreadState::executeCommand()函数中,实现传输操作。

    展开全文
  • android Binder机制

    2013-05-23 17:03:42
    Android系统中,每一个应用程序都是由一些Activity和Service组成的,一般Service运行在独立的进程中,而Activity...这就是本文中要介绍的Binder进程间通信机制了。  我们知道,Android系统是基于Linux内核的,而L

    在Android系统中,每一个应用程序都是由一些Activity和Service组成的,一般Service运行在独立的进程中,而Activity有可能运行在同一个进程中,也有可能运行在不同的进程中。那么,不在同一个进程的Activity或者Service是如何通信的呢?这就是本文中要介绍的Binder进程间通信机制了。

            我们知道,Android系统是基于Linux内核的,而Linux内核继承和兼容了丰富的Unix系统进程间通信(IPC)机制。有传统的管道(Pipe)、信号(Signal)和跟踪(Trace),这三项通信手段只能用于父进程与子进程之间,或者兄弟进程之间;后来又增加了命令管道(Named Pipe),使得进程间通信不再局限于父子进程或者兄弟进程之间;为了更好地支持商业应用中的事务处理,在AT&T的Unix系统V中,又增加了三种称为“System V IPC”的进程间通信机制,分别是报文队列(Message)、共享内存(Share Memory)和信号量(Semaphore);后来BSD Unix对“System V IPC”机制进行了重要的扩充,提供了一种称为插口(Socket)的进程间通信机制。若想进一步详细了解这些进程间通信机制,建议参考Android学习启动篇一文中提到《Linux内核源代码情景分析》一书。

            但是,Android系统没有采用上述提到的各种进程间通信机制,而是采用Binder机制,难道是因为考虑到了移动设备硬件性能较差、内存较低的特点?不得而知。Binder其实也不是Android提出来的一套新的进程间通信机制,它是基于OpenBinder来实现的。OpenBinder最先是由Be Inc.开发的,接着Palm Inc.也跟着使用。现在OpenBinder的作者Dianne Hackborn就是在Google工作,负责Android平台的开发工作。

            前面一再提到,Binder是一种进程间通信机制,它是一种类似于COM和CORBA分布式组件架构,通俗一点,其实是提供远程过程调用(RPC)功能。从英文字面上意思看,Binder具有粘结剂的意思,那么它把什么东西粘结在一起呢?在Android系统的Binder机制中,由一系统组件组成,分别是Client、Server、Service Manager和Binder驱动程序,其中Client、Server和Service Manager运行在用户空间,Binder驱动程序运行内核空间。Binder就是一种把这四个组件粘合在一起的粘结剂了,其中,核心组件便是Binder驱动程序了,Service Manager提供了辅助管理的功能,Client和Server正是在Binder驱动和Service Manager提供的基础设施上,进行Client-Server之间的通信。Service Manager和Binder驱动已经在Android平台中实现好,开发者只要按照规范实现自己的Client和Server组件就可以了。说起来简单,做起难,对初学者来说,Android系统的Binder机制是最难理解的了,而Binder机制无论从系统开发还是应用开发的角度来看,都是Android系统中最重要的组成,因此,很有必要深入了解Binder的工作方式。要深入了解Binder的工作方式,最好的方式莫过于是阅读Binder相关的源代码了,Linux的鼻祖Linus Torvalds曾经曰过一句名言RTFSC:Read The Fucking Source Code。

            虽说阅读Binder的源代码是学习Binder机制的最好的方式,但是也绝不能打无准备之仗,因为Binder的相关源代码是比较枯燥无味而且比较难以理解的,如果能够辅予一些理论知识,那就更好了。闲话少说,网上关于Binder机制的资料还是不少的,这里就不想再详细写一遍了,强烈推荐下面两篇文章:

            Android深入浅出之Binder机制

            Android Binder设计与实现 – 设计篇

            Android深入浅出之Binder机制一文从情景出发,深入地介绍了Binder在用户空间的三个组件Client、Server和Service Manager的相互关系,Android Binder设计与实现一文则是详细地介绍了内核空间的Binder驱动程序的数据结构和设计原理。非常感谢这两位作者给我们带来这么好的Binder学习资料。总结一下,Android系统Binder机制中的四个组件Client、Server、Service Manager和Binder驱动程序的关系如下图所示:

            

            1. Client、Server和Service Manager实现在用户空间中,Binder驱动程序实现在内核空间中

            2. Binder驱动程序和Service Manager在Android平台中已经实现,开发者只需要在用户空间实现自己的Client和Server

            3. Binder驱动程序提供设备文件/dev/binder与用户空间交互,Client、Server和Service Manager通过open和ioctl文件操作函数与Binder驱动程序进行通信

            4. Client和Server之间的进程间通信通过Binder驱动程序间接实现

            5. Service Manager是一个守护进程,用来管理Server,并向Client提供查询Server接口的能力

            至此,对Binder机制总算是有了一个感性的认识,但仍然感到不能很好地从上到下贯穿整个IPC通信过程,于是,打算通过下面四个情景来分析Binder源代码,以进一步理解Binder机制:

            1. Service Manager是如何成为一个守护进程的?即Service Manager是如何告知Binder驱动程序它是Binder机制的上下文管理者。

            2. Server和Client是如何获得Service Manager接口的?即defaultServiceManager接口是如何实现的。

            3. Server是如何把自己的服务启动起来的?Service Manager在Server启动的过程中是如何为Server提供服务的?即IServiceManager::addService接口是如何实现的。

            4  Service Manager是如何为Client提供服务的?即IServiceManager::getService接口是如何实现的。

            在接下来的四篇文章中,将按照这四个情景来分析Binder源代码,都将会涉及到用户空间到内核空间的Binder相关源代码。这里为什么没有Client和Server是如何进行进程间通信的情景呢? 这是因为Service Manager在作为守护进程的同时,它也充当Server角色。因此,只要我们能够理解第三和第四个情景,也就理解了Binder机制中Client和Server是如何通过Binder驱动程序进行进程间通信的了。

            为了方便描述Android系统进程间通信Binder机制的原理和实现,在接下来的四篇文章中,我们都是基于C/C++语言来介绍Binder机制的实现的,但是,我们在Android系统开发应用程序时,都是基于Java语言的,因此,我们会在最后一篇文章中,详细介绍Android系统进程间通信Binder机制在应用程序框架层的Java接口实现:

            5. Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析。

    展开全文
  • Android Binder机制原理

    2021-02-23 14:58:01
    Binder机制原理1.Android Binder机制原理 1.Android Binder机制原理 说起Binder,其实在我们开发中总是没有感觉到它的存在,但是往往在很多地方都间接的在使用它,比如我们再startAcivity的时候,必定要去调用...
  • Android Binder机制浅析

    2019-04-26 12:50:02
    Android Binder机制浅析
  • AndroidBinder机制介绍

    2021-02-26 02:15:38
    做过Android开发的同学可能有些体会,入门初期,工作内容主要是实现各式各样的UI界面,以及实现应用的业务逻辑。...我们平时使用最多的startActivity、startService都是通过binder机制与AMS所在进程进行通
  • Android Binder机制理解

    千次阅读 2016-08-24 17:55:06
    Android Binder机制理解 一、说明 Android系统中应用很广泛的但也是最难理解的就是Binder机制了,从APP组被调到系统平台组后感觉需要学的东西更多了,思考的方式也有所改变,从是什么转变到为什么(背后的设计思想...
  • 本文是Android Binder机制解析的第三篇,也是最后一篇文章。本文会讲解Binder Framework Java部分的逻辑。 Binder机制分析的前面两篇文章,请移步这里: 链接: 理解Android Binder机制(一):驱动篇. 链接: 理解...
  • 2014-09-08 Android Binder机制(十二) Binder机制的Java调用流程 2014-09-07 Android Binder机制(十一) getService详解03之 请求的反馈 2014-09-07 Android Binder机制(十) getService详解02之 请求的处理 ...
  • Android Binder机制的详解

    万次阅读 2019-01-08 21:52:21
    1.Binder机制简介 Android Binder是源于Palm的OpenBinder,它为android设备跨进程访问而设计。Binder机制从表现上看可以实现java 和native...在android系统中使用Binder机制最多的是系统服务,这些服务一般运行在特...
  • 本文是第一篇,首先会对整个Binder机制做一个架构性的讲解,然后会将大部分精力用来讲解Binder机制中最核心的部分:Binder驱动的实现。Binder源自BeInc公司开发的OpenBinder框架,后来该框架转移的PalmInc,由...
  • 理解Android Binder机制(3/3):Java层

    千次阅读 2017-06-17 02:06:24
    本文是Android Binder机制解析的第三篇,也是最后一篇文章。本文会讲解Binder Framework Java部分的逻辑。 Binder机制分析的前面两篇文章,请移步这里: 理解Android Binder机制(1/3):驱动篇 理解Android ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 38,541
精华内容 15,416
关键字:

androidbinder机制