百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Android 系统核心机制binder(03)binder C++层实现

bigegpt 2025-06-10 13:14 9 浏览

本章关键点总结 & 说明:

这里主要关注 Binder C++部分即可,看到,也是本章节的核心内容,主要就是以C++封装的框架为主来解读binder。

之前主要针对于底层驱动binder的 数据交互以及 如何注册服务、获取服务、使用服务;而android的C++层实际上仅仅是换了一种方式,加了框架的理念来更好的复用驱动层的代码而已;同时java层的封装更是为了上层的使用方便。

1 binder C++层实现框架案例

1.1 binder的C++ 相关类图 关系说明:

这里仅仅从 Binder的 客户端和服务端通信IPC角度 来看Binder的 C++实现框架,红色部分的mRemote在使用中 实际上就是 BpBinder,蓝色部分为 用户在使用 该binder C++框架时 需要自己编写的类,而其他未标明的类是系统本身自带的。该图描述了BpBinder BBinder IBinder BpRefBase IInterface BpInterface BnInterface BpHelloService BnHelloService之间的关系。

1.2 binder C++层 HelloService demo 代码实现

这里以HelloService为例,解读 binder的C++框架,看看几个关键类IHelloService、BpHelloService、BnHelloService 如何使用?

@1 IHelloService.h的实现如下:

C++
#ifndef ANDROID_IHELLOERVICE_H
#define ANDROID_IHELLOERVICE_H

#include <utils/Errors.h> // for status_t
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#define HELLO_SVR_CMD_SAYHELLO 1
#define HELLO_SVR_CMD_SAYHELLO_TO 2
#define HELLO_SVR_CMD_GET_FD 3 //后面会单独分析这个部分

namespace android {
class IHelloService: public IInterface
{
public:
DECLARE_META_INTERFACE(HelloService);
virtual void sayhello(void) = 0;
virtual int sayhello_to(const char name) = 0;
virtual int get_fd(void) = 0;
};

class BnHelloService: public BnInterface<IHelloService>
{
private:
int fd;
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel reply,
uint32_t flags = 0);
virtual void sayhello(void);
virtual int sayhello_to(const char *name);
virtual int get_fd(void); //后面会单独分析这个部分

BnHelloService();
BnHelloService(int fd);
};
}
#endif

@2 BnHelloService.cpp的实现如下(这里参考了 frameworks\av\media\libmedia\IMediaPlayerService.cpp):

C++
#define LOG_TAG "HelloService"
#include "IHelloService.h"
namespace android {
BnHelloService::BnHelloService()
{
}

BnHelloService::BnHelloService(int fd)
{
this->fd = fd;
}

status_t BnHelloService::onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags)
{
switch (code) {
case HELLO_SVR_CMD_SAYHELLO: {
sayhello();
reply->writeInt32(0); /* no exception /
return NO_ERROR;
} break;

case HELLO_SVR_CMD_SAYHELLO_TO: {
//@1 读取传入参数,并转换
int32_t policy = data.readInt32();
String16 name16_tmp = data.readString16(); / IHelloService /
String16 name16 = data.readString16();
String8 name8(name16);
//@2 调用对应函数
int cnt = sayhello_to(name8.string());

//@3 返回值转换,并发送
reply->writeInt32(0); / no exception /
reply->writeInt32(cnt);

return NO_ERROR;
} break;

case HELLO_SVR_CMD_GET_FD: {
int fd = this->get_fd();
reply->writeInt32(0); / no exception /
reply->writeDupFileDescriptor(fd);
return NO_ERROR;
} break; 
default:
return BBinder::onTransact(code, data, reply, flags);
}
}

void BnHelloService::sayhello(void)
{
static int cnt = 0;
ALOGI("say hello : %d\n", ++cnt);
}

int BnHelloService::sayhello_to(const char name)
{
static int cnt = 0;
ALOGI("say hello to %s : %d\n", name, ++cnt);
return cnt;
}

int BnHelloService::get_fd(void)
{
return fd;
}
}

@3 BpHelloService.cpp的实现如下:

C++
#include "IHelloService.h"
namespace android {

class BpHelloService: public BpInterface<IHelloService>
{
public:
BpHelloService(const sp<IBinder>& impl): BpInterface<IHelloService>(impl)
{
}

void sayhello(void)
{
Parcel data, reply;
data.writeInt32(0);
data.writeString16(String16("IHelloService"));
remote()->transact(HELLO_SVR_CMD_SAYHELLO, data, &reply);
}

int sayhello_to(const char *name)
{
Parcel data, reply;
int exception;

data.writeInt32(0);
data.writeString16(String16("IHelloService"));
data.writeString16(String16(name));
remote()->transact(HELLO_SVR_CMD_SAYHELLO_TO, data, &reply);
exception = reply.readInt32();
if (exception)
return -1;
else
return reply.readInt32();
}

int get_fd(void)
{
Parcel data, reply;
int exception;

data.writeInt32(0);
data.writeString16(String16("IHelloService"));
remote()->transact(HELLO_SVR_CMD_GET_FD, data, &reply);

exception = reply.readInt32();
if (exception)
return -1;
else
{
int rawFd = reply.readFileDescriptor();
return dup(rawFd);
}
}
};
IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService");
}

@4 客户端代码 Test_client.cpp的实现如下:

C++
#define LOG_TAG "TestService"
//#define LOG_NDEBUG 0

#include <fcntl.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <unistd.h>

#include "IHelloService.h"

using namespace android;

/* ./test_client <hello>
* ./test_client <readfile>
* ./test_client <hello> <name>
/

int main(int argc, char argv)
{
int cnt;

if (argc < 2){
ALOGI("Usage:\n");
ALOGI("%s <readfile>\n", argv[0]);
ALOGI("%s <hello|goodbye>\n", argv[0]);
ALOGI("%s <hello|goodbye> <name>\n", argv[0]);
return -1;
}

/ getService /
/ 打开驱动, mmap /
sp<ProcessState> proc(ProcessState::self());

/ 获得BpServiceManager /
sp<IServiceManager> sm = defaultServiceManager();

if (strcmp(argv[1], "hello") == 0)
{
sp<IBinder> binder = sm->getService(String16("hello"));
if (binder == 0)
{
ALOGI("can't get hello service\n");
return -1;
}

// service肯定是BpHelloServie指针
sp<IHelloService> service = interface_cast<IHelloService>(binder);

/ 调用Service的函数 /
if (argc < 3) {
service->sayhello();
ALOGI("client call sayhello");
}
else {
cnt = service->sayhello_to(argv[2]);
ALOGI("client call sayhello_to, cnt = %d", cnt);
}
}
else if (strcmp(argv[1], "readfile") == 0)
{

sp<IBinder> binder =
sm->getService(String16("hello"));

if (binder == 0)
{
ALOGI("can't get hello service\n");
return -1;
}

/ service肯定是BpHelloServie指针 /
sp<IHelloService> service = interface_cast<IHelloService>(binder);

/ 调用Service的函数 /
int fd = service->get_fd();

ALOGI("client call get_fd = %d", fd);

char buf[500];
int len;
int cnt = 0;

while (1)
{
//向 test_server 进程数据: Hello, test_server /
len = sprintf(buf, "Hello, test_server, cnt = %d", cnt++);
write(fd, buf, len);
len = read(fd, buf, 500);
buf[len] = '\0';
ALOGI("%s\n", buf);
sleep(5);
}
}
return 0;
}

@5 服务端Test_server.cpp的实现如下:

C++
#define LOG_TAG "TestService"
//#define LOG_NDEBUG 0

#include <fcntl.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include "IHelloService.h"
#define SOCKET_BUFFER_SIZE (32768U)

using namespace android;

class MyThread: public Thread { 
private:
int fd;
public: 
MyThread() {}
MyThread(int fd) { this->fd = fd; }

//说明:若返回true,循环调用此函数,返回false下一次不会再调用此函数 
bool threadLoop()
{
char buf[500];
int len;
int cnt = 0;

while(1)
{
len = read(fd, buf, 500);
buf[len] = '\0';
ALOGI("%s\n", buf);

/* 向 test_client 发出: Hello, test_client */
len = sprintf(buf, "Hello, test_client, cnt = %d", cnt++);
write(fd, buf, len);
}

return true; 
}

}; 

int main(void)
{
int sockets[2];

socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets);

int bufferSize = SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));

// 创建线程, 和test_client使用socketpiar通信
sp<MyThread> th = new MyThread(sockets[0]);
th->run(); 

// 关键点1 初始化binder
sp<ProcessState> proc(ProcessState::self());

// 关键点2 获得BpServiceManager
sp<IServiceManager> sm = defaultServiceManager();

// 关键点3
sm->addService(String16("hello"), new BnHelloService(sockets[1]));

// 关键点4 创建新的子线程,并开始处理驱动上报的消息
ProcessState::self()->startThreadPool();

// 关键点5 主线程 循环,循环并处理驱动上报的消息
IPCThreadState::self()->joinThreadPool();//辅助类 IPCThreadState的分析

return 0;
}

@6 最后描述下 Android.mk的实现

Bash
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
BnHelloService.cpp \
BpHelloService.cpp \
test_server.cpp

LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
liblog \
libbinder 


LOCAL_MODULE:= test_server
LOCAL_32_BIT_ONLY := true

include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
BpHelloService.cpp \
test_client.cpp

LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
liblog \
libbinder 


LOCAL_MODULE:= test_client
LOCAL_32_BIT_ONLY := true

include $(BUILD_EXECUTABLE)

几段代码的整体说明:

前三段代码实现了HelloService整个服务(接口IHelloService 和BpHelloService 和 BnHelloService)

服务端TestServer实现了Hello服务的注册和socket通信架构机制(读& 写)。

客户端TestClient实现了Hello服务的获取和使用,同时 获取了fd(服务端的socket句柄)并使用

Android.mk的实现,可以直接编译即可使用。

根据上面的例子基本上就可以写出一个基于Binder的 C++ demo程序,如果仅仅是使用binder的话,那已经足够了。

2 binder C++层实现 BpServiceManager

这一部分专门解读下 BpServiceManager的通信流程框架和部分代码,因为针对于系统的ServiceManager服务而言,它本身就相当于BnServiceManager的角色,而我们在分析Binder C++层代码时,当时也陷入了一个误区,觉得有BpXXX就一定要有BnXXX,实际上是不一定的,ServiceManager本身就是一个很好的例子。

2.1 BpServiceManager 的单边类关系框架图如下:

跟1.1的框架图相比,实际上是少了BnInterface那一半的,而这一半实际上就是开机启动的那个程序 servicemanager,在下一章节中我们会专门讲解到。

2.2 IServiceManager的实现说明

@1 IServiceManager.h的实现如下:

C++
#ifndef ANDROID_ISERVICE_MANAGER_H
#define ANDROID_ISERVICE_MANAGER_H

#include <binder/IInterface.h>
#include <binder/IPermissionController.h>
#include <utils/Vector.h>
#include <utils/String16.h>

namespace android {
class IServiceManager : public IInterface
{
public:
DECLARE_META_INTERFACE(ServiceManager);

virtual sp<IBinder> getService( const String16& name) const = 0;
virtual sp<IBinder> checkService( const String16& name) const = 0;
virtual status_t addService( const String16& name,
const sp<IBinder>& service,
bool allowIsolated = false) = 0;
virtual Vector<String16> listServices() = 0;

enum {
GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
CHECK_SERVICE_TRANSACTION,
ADD_SERVICE_TRANSACTION,
LIST_SERVICES_TRANSACTION,
};
};

sp<IServiceManager> defaultServiceManager();

template<typename INTERFACE>
status_t getService(const String16& name, sp<INTERFACE>* outService)
{
const sp<IServiceManager> sm = defaultServiceManager();
if (sm != NULL) {
outService = interface_cast<INTERFACE>(sm->getService(name));
if ((outService) != NULL) return NO_ERROR;
}
return NAME_NOT_FOUND;
}
//...

class BnServiceManager : public BnInterface<IServiceManager>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
}; // namespace android

#endif // ANDROID_ISERVICE_MANAGER_H

@2 IServiceManager.cpp的实现如下:

C++
#define LOG_TAG "ServiceManager"

#include <binder/IServiceManager.h>

#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>

#include <private/binder/Static.h>

#include <unistd.h>

namespace android {

sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;

{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}

return gDefaultServiceManager;
}
//。。。
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}

virtual sp<IBinder> getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
sp<IBinder> svc = checkService(name);
if (svc != NULL) return svc;
ALOGI("Waiting for service %s...\n", String8(name).string());
sleep(1);
}
return NULL;
}

virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}

virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}

virtual Vector<String16> listServices()
{
Vector<String16> res;
int n = 0;

for (;;) {
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeInt32(n++);
status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply);
if (err != NO_ERROR)
break;
res.add(reply.readString16());
}
return res;
}
};

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

// ----------------------------------------------------------------------

status_t BnServiceManager::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
//printf("ServiceManager received: "); data.print();
switch(code) {
case GET_SERVICE_TRANSACTION: {
CHECK_INTERFACE(IServiceManager, data, reply);
String16 which = data.readString16();
sp<IBinder> b = const_cast<BnServiceManager*>(this)->getService(which);
reply->writeStrongBinder(b);
return NO_ERROR;
} break;
//...
default:
return BBinder::onTransact(code, data, reply, flags);
}
}

}; // namespace android

总结下,这两个文件主要实现了IServiceManager,BpServiceManager,BnServiceManager,然而这里最让人疑惑的就是BnServiceManager不是由 servicemanager替换了吗?那为什么还有BnServiceManager的存在?

BnServiceManager并没有在系统中注册,因此也就无法在驱动层生成对应的binder_node节点,事实上也没必要注册;因为servicemanager开机就启动,已经替代了所谓的BnServiceManager,同时在驱动层 给自己创建了对应的binder_node节点,所以最后的答案很简单,因为BnServiceManager压根就没有使用,只是一个摆设而已,真正实现功能的是servicemanager。

相关推荐

ActiveAndroid使用(对象化数据库)

配置模块的build.gradlerepositories{mavenCentral()mavenLocal()maven{url"https://oss.sonatype.org/conte...

AndroidStudio下的依赖管理(android app依赖外部jar包)

在开发中用第三方库是很常见的事,如何在AndroidStudio下管理这些依赖呢?这就是这篇文章的目的。目录Maven/Ivy仓库依赖Module依赖aar文件依赖jar文件依赖例子完整代码一、Mav...

Android Studio之gradle的配置与介绍

1、gradle的简单介绍Gradle是可以用于Android开发的新一代的BuildSystem,也是AndroidStudio默认的build工具。其实Gradle脚本是基于一种JVM语言—...

Android中的run-as命令带来的安全问题

一、前言最近一周比较忙,没时间写东西了,今天继续开始我们今天的话题:run-as命令,在上周的开发中,遇到一个问题,就是在使用run-as命令的时候出现了一个错误,不过当时因为工作进度的问题,这问题就...

Android系统级深入开发——input驱动程序

1、Input驱动程序是Linux输入设备的驱动程序,分成游戏杆(joystick)、鼠标(mouse和mice)和事件设备(Eventqueue)3种驱动程序。其中事件驱动程序是目前通用的驱动程序...

Android项目中如何用好构建神器Gradle?

CSDN移动将持续为您优选移动开发的精华内容,共同探讨移动开发的技术热点话题,涵盖移动应用、开发工具、移动游戏及引擎、智能硬件、物联网等方方面面。如果您想投稿、参与内容翻译工作,或寻求近匠报道,请发送...

Android Studio自定义文件类头(android studio自定义标题栏)

--简书作者谢恩铭转载请注明出处今天给大家介绍一个很简单的"小"技巧。平时,我们在AndroidStudio中开发Android时,总免不了要创建新的文件,也许是Java文件,也许是C...

C语言#include头文件真的是插入代码吗?

若文章对您有帮助,欢迎关注程序员小迷。助您在编程路上越走越好!编译器理论和实作既是又不是。从编译器理论理解,#include头文件"相当于"插入了头文件的代码,以供源代码引用(宏定...

Android 系统核心机制binder(03)binder C++层实现

本章关键点总结&说明:这里主要关注BinderC++部分即可,看到,也是本章节的核心内容,主要就是以C++封装的框架为主来解读binder。之前主要针对于底层驱动binder的数据交互以及...

Java对象序列化与反序列化的那些事

Java对象序列化与反序列化的那些事在Java的世界里,对象序列化和反序列化就像一对孪生兄弟,它们共同构成了Java对象存储和传输的基础。如果你曾经尝试将对象保存到文件中,或者在网络中传输对象,那么你...

Java对象序列化剖析(java 对象序列化)

对象序列化的目的1)希望将Java对象持久化在文件中2)将Java对象用于网络传输实现方式如果希望一个类的对象可以被序列化/反序列化,那该类必须实现java.io.Serializable接口或jav...

C++模板 - 16(SFINAE)(c++模板编程)

C++支持函数重载,同一个函数名,只要它的签名不一样,可以声明若干个版本(这个特性也是必须的,不然构造函数就只能有一个了)。现在函数的重载集合中又加入了新的成员-函数模板,事情就变得越发有趣起来,...

NewtoSoft.Json相关使用技巧(newtosoft.json相关使用技巧有哪些)

  本篇将为大家介绍Newtonsoft.Json的一些高级用法,可以修改很少的代码解决上述问题。Newtonsoft.Json介绍  在做开发的时候,很多数据交换都是以json格式传输的。而使用Js...

C#调用DeepSeek API(c#调用deepseek api 流式输出)

一、官方网站二、DeepSeek测试DeepSeek三大适用模式:基础模型(V3)、深度思考(R1)、联网搜索。基础模型(V3)深度思考(R1)联网搜索三、C#调用DeepSeekAPI核心代码//...

.NET性能系列文章二:Newtonsoft.Json vs System.Text.Json

微软终于追上了?图片来自GlennCarstens-Peters[1]Unsplash[2]欢迎来到.NET性能系列的另一章。这个系列的特点是对.NET世界中许多不同的主题进行研究、基准和比较...