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世界中许多不同的主题进行研究、基准和比较...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- resize函数 (64)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- mybatis大于等于 (64)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- logstashinput (65)
- hadoop端口 (65)
- vue阻止冒泡 (67)
- oracle时间戳转换日期 (64)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)