Binder机制详解与编程实例
Binder基本概念
什么是Binder?
Binder是Android系统中最重要的进程间通信(IPC)机制,它具有以下特点:
- 高性能:只需一次数据拷贝
- 安全性:基于UID/PID的身份验证
- 面向对象:类似远程方法调用(RPC)
- 引用计数:自动管理对象生命周期
Binder架构组件
- Binder驱动 - 内核空间的字符设备
/dev/binder - Service Manager - 系统服务管理器
- Binder服务 - 提供服务的进程
- 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!
关键概念总结
-
Binder通信流程:
- 客户端通过ServiceManager查找服务
- 获取服务的Binder代理
- 通过代理进行远程方法调用
-
数据传输:
- 使用Parcel进行数据序列化
- 支持基本类型和Binder对象
-
生命周期管理:
- 使用sp智能指针管理对象生命周期
- 死亡通知机制处理服务异常退出
-
线程安全:
- 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服务
- 定义接口(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编程的基本概念。
6226

被折叠的 条评论
为什么被折叠?



