您的位置:

Android Binder机制详解

一、Binder机制概述

Binder是一种进程间通信机制,它是Android系统中非常重要的一部分。在Android系统中,应用程序需要和设备驱动程序、系统服务等进程进行通信,这就需要使用到Binder机制。

Binder机制是基于线程的进程间通信机制。Android系统中的每个进程都有一个Binder驱动,它负责创建Binder对象并维护Binder对象之间的连接。通过Binder机制,不同的进程可以共享数据,实现共享内存,同时也可以进行RPC(远程过程调用)。

Binder驱动会在内核层面为每个Binder对象分配一个唯一的标识符——Binder物理地址(Binder node)。

二、Binder机制的实现

1、Binder对象

Binder对象是Android系统中的核心对象,它是进程间通信的基础。在Binder机制中,每个进程通过创建接口类(Binder类)实现一个Binder对象,在进程间通信时将Binder对象传递给其他进程。

在Java层,Binder类是AIDL(Android Interface Definition Language)文件编译后生成的Java类,所有的Binder接口定义都必须使用AIDL文件来定义。

// IMyAidlInterface.aidl文件
interface IMyAidlInterface {
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString);
}

// IMyAidlInterface.java文件
public interface IMyAidlInterface extends android.os.IInterface {
...
}

在C++层,Binder对象则是继承自BBinder的类,BBinder类实现了Binder对象的基本功能。

// IBinder.h文件
class IBinder : public IInterface {
public:
    DECLARE_META_INTERFACE(Binder);

    virtual status_t    transact(   uint32_t        code,
                                    const Parcel&   data,
                                    Parcel*         reply,
                                    uint32_t        flags = 0) = 0;
...
};

// BBinder.h文件
class BBinder : public BnBinder {
public:
    virtual status_t    onTransact( uint32_t        code,
                                    const Parcel&   data,
                                    Parcel*         reply,
                                    uint32_t        flags = 0);
...
};

2、Binder驱动

Binder驱动是Android系统中专门用来处理Binder对象的进程,它主要负责的是Binder对象之间的连接、维护和转发等工作。

Binder驱动会为每个进程提供一个Binder设备文件(/dev/binder),每个进程都必须通过/dev/binder文件与Binder驱动通信,进行Binder对象的创建、连接和通信等操作。

3、Binder节点

当进程创建一个Binder对象时,Binder驱动会为该Binder对象分配一个唯一的标识符——Binder节点(Binder node),用于区分不同的Binder对象。

Binder节点是唯一的长整型标识符,其内部存储表示为一个指针。在Java层,Binder节点实际上是Java对象的引用。

在C++层,Binder节点指向的是Binder对象的头部,包括一个指向Binder对象的引用计数、一个指向Binder对象的类型所在的引用计数表的指针,以及类型ID和事务ID。

三、Binder机制的使用

1、创建和传递Binder对象

在创建Binder对象和将Binder对象传递给其他进程时,需要使用相应的API接口来完成。

在Java层,创建Binder对象需要使用Binder类,将Binder对象传递给其他进程需要使用IBinder接口。

// 创建Binder对象
private final IBinder mBinder = new MyBinder();

// 将Binder对象传递给其他进程
Intent intent = new Intent(this, MyService.class);
intent.putExtra("binder", mBinder);
startService(intent);

在C++层,创建Binder对象需要使用BnXXX或BpXXX类,将Binder对象传递给其他进程需要使用IBinder接口。

// 创建Binder对象
class MyBinder : public BnMyInterface {
...
};

// 将Binder对象传递给其他进程
sp sm = defaultServiceManager();
sm->addService(String16("my_service"), new MyService());

  

2、Binder对象的连接和阻塞

在进程间通信过程中,连接相关的操作都是在Binder驱动中完成的。

当一个进程调用Binder对象的transact方法来与另一个进程进行通信时,如果此时另一个进程还没有准备好接受数据,那么当前进程就会被阻塞,直到另一个进程准备好接受数据。

在Java层,使用Binder类连接和阻塞Binder对象需要使用while循环,不断调用transact方法,直到连接成功。

// 连接Binder对象
mService = IMyInterface.Stub.asInterface(service);

// 阻塞Binder对象
while (mService == null) {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    mService = IMyInterface.Stub.asInterface(service);
}

在C++层,使用IBinder接口连接和阻塞Binder对象需要使用IPCThreadState类,IPCThreadState类提供了很多阻塞式的连接和传输方法。

// 连接Binder对象
sp binder = defaultServiceManager()->getService(String16("my_service"));

// 阻塞Binder对象
if (binder == nullptr) {
    binder = IPCThreadState::self()->waitForService(String16("my_service"));
}

  

3、Binder对象的传输和接收

Binder对象的传输和接收都是通过Binder驱动来实现的,具体的传输和接收过程由驱动进行管理。

在Java层,向Binder对象发送数据需要创建Parcel对象,将需要传输的数据打包到Parcel中,然后通过transact方法将Parcel传递给另一个进程。接收数据时,需要在onTransact方法中解析Parcel对象,获取传输过来的数据。

// 发送数据
Parcel data = Parcel.obtain();
data.writeInt(123);
data.writeLong(456);
service.transact(1, data, null, 0);

// 接收数据
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    switch (code) {
        case 1: {
            int arg1 = data.readInt();
            long arg2 = data.readLong();

            Log.d(TAG, "arg1: " + arg1 + ", arg2: " + arg2);
            break;
        }
    }

    return super.onTransact(code, data, reply, flags);
}

在C++层,发送和接收数据需要使用Parcel类,具体的过程与Java层类似。Parcel类提供了读写基本类型和创建自定义数据结构的方法,可以方便地进行数据的传输和接收。

// 发送数据
Parcel data;
data.writeInt32(123);
data.writeInt64(456);
binder->transact(1, data, &reply);

// 接收数据
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
    switch (code) {
        case 1: {
            int32_t arg1 = data.readInt32();
            int64_t arg2 = data.readInt64();

            ALOGD("arg1: %d, arg2: %lld", arg1, arg2);
            break;
        }
    }

    return BBinder::onTransact(code, data, reply, flags);
}

四、总结

本文介绍了Android系统中非常重要的一部分——Binder机制。Binder机制是进程间通信的核心机制,它可以实现进程间数据的共享和RPC等功能。我们从Binder机制的概述、实现和使用三个方面对Binder机制进行了详细阐述,希望能够帮助读者更好地理解和使用Binder机制。

Android Binder机制详解

2023-05-24
深入理解Android的Binder机制

2023-05-14
Android Binder:实现进程间通信的核心机制

Android系统的进程间通信(IPC)机制是整个系统中最重要的部分之一,这个机制让不同的进程之间能够交换数据和信息。在Android系统中,主要采用的IPC机制是Binder机制。Binder机制的

2023-12-08
解密Android Binder机制:实现进程间通信

一、前言 在Android系统中,各个应用程序之间需要进行进程间通信,以实现数据共享和交互功能。Binder机制是Android系统中最核心、最基础的进程间通信方式。本文将对Android Binde

2023-12-08
Android Binder机制:实现进程间通信的核心技术

2023-05-14
印象笔记记录java学习(Java成长笔记)

2022-11-12
java方法整理笔记(java总结)

2022-11-08
RemoteView – Android系统内部通讯机制

2023-05-19
发篇java复习笔记(java课程笔记)

2022-11-09
java客户端学习笔记(java开发笔记)

2022-11-14
阿里云笔记的功能与使用详解

2023-05-21
java学习笔记(java初学笔记)

2022-11-14
java包笔记,Java语言包

2022-11-18
Android应用快速启动的关键-Zygote进程解析

Android应用在启动过程中,Zygote进程起到了至关重要的作用。Zygote进程是一个特殊的进程,它会在系统启动时被创建,并始终保持运行状态,负责孵化新的进程。在使用应用时,Zygote进程可以

2023-12-08
python基础学习整理笔记,Python课堂笔记

2022-11-21
深入了解IBinder

2023-05-18
java笔记,大学java笔记

2022-11-28
java笔记,尚硅谷java笔记

2022-12-01
Android中的HIDL:硬件抽象接口定义语言

一、为什么需要HIDL? 在Android系统中,访问硬件的方式通常是通过HAL(Hardware Abstraction Layer)来实现的。但是,HAL在某些方面存在着不足,例如:为了适配不同的

2023-12-08
Android Parcel:轻松实现进程间通信

2023-05-14