Binder机制详解与编程实例

新星杯·14天创作挑战营·第17期 10w+人浏览 490人参与

Binder机制详解与编程实例

Binder基本概念

什么是Binder?

Binder是Android系统中最重要的进程间通信(IPC)机制,它具有以下特点:

  • 高性能:只需一次数据拷贝
  • 安全性:基于UID/PID的身份验证
  • 面向对象:类似远程方法调用(RPC)
  • 引用计数:自动管理对象生命周期

Binder架构组件

  1. Binder驱动 - 内核空间的字符设备 /dev/binder
  2. Service Manager - 系统服务管理器
  3. Binder服务 - 提供服务的进程
  4. Binder客户端 - 使用服务的进程

代码实例

实例1:Binder服务端基础框架

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/IInterface.h>
#include <binder/Binder.h>
#include <binder/Parcel.h>
#include <utils/Log.h>
#include <utils/String16.h>

using namespace android;

// 1. 定义服务接口
class IMyService : public IInterface {
public:
    DECLARE_META_INTERFACE(MyService);  // 声明元接口
    
    // 定义服务方法
    virtual int add(int a, int b) = 0;
    virtual String16 echo(const String16& message) = 0;
};

// 2. 实现BnInterface(服务端桩)
class BnMyService : public BnInterface<IMyService> {
public:
    virtual status_t onTransact(uint32_t code, 
                               const Parcel& data, 
                               Parcel* reply, 
                               uint32_t flags = 0) override;
};

// 3. 实现具体的服务
class MyService : public BnMyService {
public:
    // 实现add方法
    int add(int a, int b) override {
        ALOGD("MyService::add called with %d + %d", a, b);
        return a + b;
    }
    
    // 实现echo方法
    String16 echo(const String16& message) override {
        ALOGD("MyService::echo called with: %s", String8(message).string());
        return String16("Echo: ") + message;
    }
};

// 4. 实现onTransact方法
status_t BnMyService::onTransact(uint32_t code, 
                                const Parcel& data, 
                                Parcel* reply, 
                                uint32_t flags) {
    ALOGD("BnMyService::onTransact code: %u", code);
    
    // 检查接口
    CHECK_INTERFACE(IMyService, data, reply);
    
    switch(code) {
        case ADD: {
            // 从数据包读取参数
            int a = data.readInt32();
            int b = data.readInt32();
            ALOGD("Received add request: %d + %d", a, b);
            
            // 调用实际方法
            int result = add(a, b);
            
            // 将结果写入回复包
            reply->writeInt32(result);
            return NO_ERROR;
        } break;
        
        case ECHO: {
            // 读取字符串参数
            String16 message = data.readString16();
            ALOGD("Received echo request: %s", String8(message).string());
            
            // 调用实际方法
            String16 result = echo(message);
            
            // 写入回复
            reply->writeString16(result);
            return NO_ERROR;
        } break;
        
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

// 5. 实现接口描述符
IMPLEMENT_META_INTERFACE(MyService, "com.example.IMyService");

// 6. 服务主函数
int main() {
    // 设置Binder线程池
    sp<ProcessState> proc(ProcessState::self());
    proc->startThreadPool();
    
    // 获取服务管理器
    sp<IServiceManager> sm = defaultServiceManager();
    
    // 创建服务实例
    sp<MyService> service = new MyService();
    
    // 注册服务
    status_t status = sm->addService(String16("myservice"), service);
    if (status != NO_ERROR) {
        ALOGE("Failed to register service: %d", status);
        return -1;
    }
    
    ALOGD("MyService registered successfully");
    
    // 进入Binder循环
    IPCThreadState::self()->joinThreadPool();
    return 0;
}

实例2:Binder客户端

#include <binder/IServiceManager.h>
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <utils/Log.h>
#include <utils/String16.h>

using namespace android;

// 客户端代理类
class BpMyService : public BpInterface<IMyService> {
public:
    BpMyService(const sp<IBinder>& impl) 
        : BpInterface<IMyService>(impl) {}
    
    // 实现远程add方法调用
    int add(int a, int b) override {
        Parcel data, reply;
        
        // 写入接口令牌
        data.writeInterfaceToken(IMyService::getInterfaceDescriptor());
        
        // 写入参数
        data.writeInt32(a);
        data.writeInt32(b);
        
        ALOGD("BpMyService::add sending request: %d + %d", a, b);
        
        // 远程调用
        status_t status = remote()->transact(ADD, data, &reply);
        if (status != NO_ERROR) {
            ALOGE("BpMyService::add transaction failed: %d", status);
            return -1;
        }
        
        // 读取结果
        int result = reply.readInt32();
        ALOGD("BpMyService::add received result: %d", result);
        
        return result;
    }
    
    // 实现远程echo方法调用
    String16 echo(const String16& message) override {
        Parcel data, reply;
        
        // 写入接口令牌
        data.writeInterfaceToken(IMyService::getInterfaceDescriptor());
        
        // 写入参数
        data.writeString16(message);
        
        ALOGD("BpMyService::echo sending: %s", String8(message).string());
        
        // 远程调用
        status_t status = remote()->transact(ECHO, data, &reply);
        if (status != NO_ERROR) {
            ALOGE("BpMyService::echo transaction failed: %d", status);
            return String16("Error");
        }
        
        // 读取结果
        String16 result = reply.readString16();
        ALOGD("BpMyService::echo received: %s", String8(result).string());
        
        return result;
    }
};

// 实现接口宏
IMPLEMENT_META_INTERFACE(MyService, "com.example.IMyService");

// 客户端主函数
int main() {
    // 初始化Binder
    sp<ProcessState> proc(ProcessState::self());
    
    // 获取服务管理器
    sp<IServiceManager> sm = defaultServiceManager();
    
    // 查找服务
    sp<IBinder> binder = sm->getService(String16("myservice"));
    if (binder == nullptr) {
        ALOGE("Cannot find myservice");
        return -1;
    }
    
    // 创建代理
    sp<IMyService> service = interface_cast<IMyService>(binder);
    if (service == nullptr) {
        ALOGE("Cannot cast to IMyService");
        return -1;
    }
    
    ALOGD("Successfully connected to MyService");
    
    // 测试add方法
    int result1 = service->add(5, 3);
    ALOGD("5 + 3 = %d", result1);
    
    // 测试echo方法
    String16 result2 = service->echo(String16("Hello Binder!"));
    ALOGD("Echo result: %s", String8(result2).string());
    
    // 再次测试
    int result3 = service->add(10, 20);
    ALOGD("10 + 20 = %d", result3);
    
    return 0;
}

实例3:异步Binder调用

#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/IBinder.h>
#include <utils/Log.h>

using namespace android;

// 异步回调接口
class IMyCallback : public IInterface {
public:
    DECLARE_META_INTERFACE(MyCallback);
    
    virtual void onResult(int result) = 0;
    virtual void onError(const String16& error) = 0;
};

// 异步服务接口
class IMyAsyncService : public IInterface {
public:
    DECLARE_META_INTERFACE(MyAsyncService);
    
    virtual void asyncAdd(int a, int b, const sp<IMyCallback>& callback) = 0;
};

// 实现回调
class MyCallback : public BnInterface<IMyCallback> {
public:
    void onResult(int result) override {
        ALOGD("MyCallback::onResult: %d", result);
    }
    
    void onError(const String16& error) override {
        ALOGE("MyCallback::onError: %s", String8(error).string());
    }
};

// 异步服务实现
class MyAsyncService : public BnInterface<IMyAsyncService> {
public:
    void asyncAdd(int a, int b, const sp<IMyCallback>& callback) override {
        ALOGD("MyAsyncService::asyncAdd: %d + %d", a, b);
        
        // 模拟异步操作
        std::thread([=]() {
            // 模拟计算延迟
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            
            int result = a + b;
            
            // 回调结果
            if (callback != nullptr) {
                callback->onResult(result);
            }
        }).detach();
    }
    
    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override {
        CHECK_INTERFACE(IMyAsyncService, data, reply);
        
        switch(code) {
            case ASYNC_ADD: {
                int a = data.readInt32();
                int b = data.readInt32();
                sp<IMyCallback> callback = interface_cast<IMyCallback>(data.readStrongBinder());
                
                asyncAdd(a, b, callback);
                return NO_ERROR;
            }
            default:
                return BBinder::onTransact(code, data, reply, flags);
        }
    }
};

// 实现接口宏
IMPLEMENT_META_INTERFACE(MyAsyncService, "com.example.IMyAsyncService");
IMPLEMENT_META_INTERFACE(MyCallback, "com.example.IMyCallback");

实例4:Binder死亡通知

#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <utils/Log.h>

using namespace android;

// 死亡接收器
class MyDeathRecipient : public IBinder::DeathRecipient {
public:
    MyDeathRecipient() {
        ALOGD("MyDeathRecipient created");
    }
    
    ~MyDeathRecipient() {
        ALOGD("MyDeathRecipient destroyed");
    }
    
    void binderDied(const wp<IBinder>& who) override {
        ALOGE("Binder service died!");
        // 这里可以处理服务死亡后的逻辑,比如重新连接
    }
};

// 在客户端使用死亡通知
class BinderClientWithDeathNotify {
private:
    sp<IMyService> mService;
    sp<MyDeathRecipient> mDeathRecipient;

public:
    bool connectToService() {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder = sm->getService(String16("myservice"));
        
        if (binder == nullptr) {
            ALOGE("Cannot find service");
            return false;
        }
        
        // 设置死亡通知
        mDeathRecipient = new MyDeathRecipient();
        binder->linkToDeath(mDeathRecipient);
        
        mService = interface_cast<IMyService>(binder);
        return mService != nullptr;
    }
    
    void disconnect() {
        if (mService != nullptr) {
            // 取消死亡通知
            mService->asBinder()->unlinkToDeath(mDeathRecipient);
            mService.clear();
        }
    }
};

编译和运行

Android.mk 编译文件示例

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := myservice
LOCAL_SRC_FILES := MyService.cpp
LOCAL_SHARED_LIBRARIES := libbinder libutils liblog
include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)
LOCAL_MODULE := myclient
LOCAL_SRC_FILES := MyClient.cpp
LOCAL_SHARED_LIBRARIES := libbinder libutils liblog
include $(BUILD_EXECUTABLE)

预期运行结果

服务端输出:

MyService registered successfully
BnMyService::onTransact code: 1
Received add request: 5 + 3
MyService::add called with 5 + 3
BnMyService::onTransact code: 2
Received echo request: Hello Binder!
MyService::echo called with: Hello Binder!

客户端输出:

Successfully connected to MyService
BpMyService::add sending request: 5 + 3
BpMyService::add received result: 8
5 + 3 = 8
BpMyService::echo sending: Hello Binder!
BpMyService::echo received: Echo: Hello Binder!
Echo result: Echo: Hello Binder!

关键概念总结

  1. Binder通信流程

    • 客户端通过ServiceManager查找服务
    • 获取服务的Binder代理
    • 通过代理进行远程方法调用
  2. 数据传输

    • 使用Parcel进行数据序列化
    • 支持基本类型和Binder对象
  3. 生命周期管理

    • 使用sp智能指针管理对象生命周期
    • 死亡通知机制处理服务异常退出
  4. 线程安全

    • Binder自动处理多线程访问
    • 使用线程池处理并发请求

这些实例展示了Binder编程的核心概念,在实际的Android系统开发中,Binder是系统服务和应用服务的基础通信机制。

由于Binder是Android特有的进程间通信机制,它主要在Android系统中使用,因此代码实例将基于Android环境。但是,请注意,在Android中,Binder通常用于系统服务和应用程序之间的通信,而且大多数情况下,我们使用AIDL(Android接口定义语言)来定义Binder接口。不过,为了深入理解,我们可以通过C++层来看Binder的基本使用。

由于Binder机制相当复杂,我们将从一个简单的例子开始,这个例子将展示如何创建一个简单的Binder服务并在客户端调用它。请注意,这个例子需要在Android系统环境下运行,并且需要相应的权限。

由于在Android中,Binder驱动通常只对系统进程开放,普通应用可能无法直接使用Binder驱动(除非是在系统应用或具有相应权限的情况下)。因此,以下示例通常用于系统级开发。

我们将创建一个简单的Binder服务,它有一个方法返回一个字符串。然后创建一个客户端来调用这个方法。

步骤:

定义Binder接口(使用AIDL或直接继承IInterface)。

实现Binder服务。

注册Binder服务到ServiceManager。

客户端获取Binder服务并调用方法。

但是,由于在Android中,直接使用C++层Binder需要涉及很多底层细节,而且通常系统服务才会这样做,我们将提供一个简化的示例,并假设在合适的环境中运行。

由于代码量较大,我们将分步骤进行。注意,以下代码是高度简化的,并且可能需要特定的环境才能运行。

由于Binder的复杂性,我们这里只提供一个概念性的示例,实际开发中建议使用AIDL。

以下是一个简单的Binder服务的C++实现示例:

注意: 这个例子需要在Android源码环境中编译,并且需要系统权限。

示例:简单的Binder服务

  1. 定义接口(IHelloService.h) ```cpp
    #ifndef IHELLO_SERVICE_H
    #define IHELLO_SERVICE_H

#include <binder/IInterface.h>
#include <binder/Parcel.h>

// 定义接口的描述符
#define HELLO_SERVICE_DESCRIPTOR “android.demo.IHelloService”

// 定义接口 class IHelloService : public android::IInterface { public:
// 宏,用于声明接口描述符和asInterface方法
DECLARE_META_INTERFACE(HelloService);

// 定义一个方法:sayHello
virtual android::String8 sayHello() = 0; };

// 定义Binder接口的Bn端(服务端)和Bp端(客户端代理) class BnHelloService : public
android::BnInterface { public:
virtual android::status_t onTransact(uint32_t code,
const android::Parcel& data,
android::Parcel* reply,
uint32_t flags = 0); };

#endif // IHELLO_SERVICE_H ```
2. 实现接口(IHelloService.cpp)

#include "IHelloService.h"

// 使用宏实现接口描述符和asInterface方法 namespace android {

IMPLEMENT_META_INTERFACE(HelloService, HELLO_SERVICE_DESCRIPTOR);

// BnHelloService的onTransact方法 status_t
BnHelloService::onTransact(uint32_t code, 
                                    const Parcel& data, 
                                    Parcel* reply, 
                                    uint32_t flags) {
    switch (code) {
        case SAY_HELLO: {
            CHECK_INTERFACE(IHelloService, data, reply);
            // 调用sayHello方法并写入回复
            String8 str = sayHello();
            reply->writeString8(str);
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    } }

} // namespace android ```
3. 实现服务(HelloService.cpp)

```cpp
#include "IHelloService.h"

namespace android {

class HelloService : public BnHelloService { public:
    static void instantiate() {
        // 注册服务到ServiceManager
        defaultServiceManager()->addService(
            String16(HELLO_SERVICE_DESCRIPTOR), new HelloService());
    }

    // 实现sayHello方法
    virtual String8 sayHello() {
        return String8("Hello from Binder Service!");
    } };

} // namespace android

int main() {
    // 实例化并注册服务
    android::HelloService::instantiate();
    
    // 启动线程池,等待客户端请求
    android::ProcessState::self()->startThreadPool();
    android::IPCThreadState::self()->joinThreadPool();
    
    return 0; } ```
4. 客户端(Client.cpp)

```cpp
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "IHelloService.h"

int main() {
    // 获取服务管理器
    sp<IServiceManager> sm = defaultServiceManager();
    
    // 通过描述符获取HelloService
    sp<IBinder> binder = sm->getService(String16(HELLO_SERVICE_DESCRIPTOR));
    if (binder == nullptr) {
        printf("无法获取HelloService\n");
        return -1;
    }
    
    // 将IBinder对象转换为IHelloService接口
    sp<IHelloService> service = interface_cast<IHelloService>(binder);
    if (service == nullptr) {
        printf("无法转换接口\n");
        return -2;
    }
    
    // 调用远程方法
    String8 str = service->sayHello();
    printf("从服务端收到的消息: %s\n", str.string());
    
    return 0; } ```编译和运行 由于Binder服务通常需要系统权限,并且需要添加到系统的构建文件中,因此编译和运行需要Android源码环境。

运行结果 如果服务端已经运行(在设备上或模拟器中),客户端运行后应该输出:

> 从服务端收到的消息: Hello from Binder Service! 注意事项 这个示例非常简化,实际开发中需要处理更多的错误和边界情况。

Binder通信涉及序列化和反序列化,需要仔细处理Parcel的读写。

服务端和客户端都需要在Android系统中运行,并且需要相应的权限。

由于Binder机制的复杂性,这个示例只是入门级介绍。在实际项目中,建议使用AIDL来定义Binder接口,这样可以自动生成大部分模板代码。

希望这个示例能帮助你理解Binder编程的基本概念。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值