1.Binder机制简介
Android Binder是源于Palm的OpenBinder,它为android设备跨进程访问而设计。Binder机制从表现上看可以实现java 和native层的对象实例可以从一个进程访问到另一个进程,从而透明的实现跨进程的调用。调用者感觉不到自己的请求是在另一个进程中完成并返回结果的。在android系统中使用Binder机制*多的是系统服务,这些服务一般运行在特定的进程中。服务的使用者成为Client,Client一般是应用程序,是跨进程访问的请求发起者。运行行在特定进程中的服务被成为server,这些server用于接受client端发起的请求并处理具体相关业务并返回结果。
Android系统中的Binder机制涉及java和c++层两部分,使java和native层都可以实现Binder的client、server逻辑并通过系统的/dev/binder虚拟设备提供的跨进程能力发起请求和接受请求处理业务返回结果。其中java层的Binder是对C++层Binder机制的上层封装,通过JNI的方式调用到C++的实现逻辑中。
我将通过分别分析C++层的实现和java的封装两部分分析Binder机制。
2.C++层Binder的实现
我通过分析MediaServer的实现逻辑通过阅读源码了解一下Binder的实现逻辑.MediaServer执行程序的入口是main()方法:
…/frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc __unused, char** argv)
{
…………………
//获取一个ProcessState对象,同时通过pen_driver()打开/dev/binder的虚拟设备,通过mmap()为binder分配一块空间用于通信读写,通过
//iotrl()为binder指定线程数
sp<ProcessState> proc(ProcessState::self());
//获取一个IServerManager对象,用于服务注册
sp<IServiceManager> sm = defaultServiceManager();
ALOGI(“ServiceManager: %p”, sm.get());
//初始化音频系统AudioFlinger
AudioFlinger::instantiate();
//多媒体服务初始化
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
//cameraServer 相机服务
CameraService::instantiate();
//音频系统AudioPolicy服务
AudioPolicyService::instantiate();
SoundTriggerHwService::instantiate();
RadioService::instantiate();
registerExtensions();
//创建线程池?
ProcessState::self()->startThreadPool();
//加入线程池?
IPCThreadState::self()->joinThreadPool();
………………..
}
1.1ProcessState的作用
从main_mediaServer.cpp的main()方法中可以看到 sp proc(ProcessState::self())获取一个ProcessState对象,先看一下ProcessState::self()函数都做了什么:
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
//创建一个新的ProcessState对象
gProcess = new ProcessState;
return gProcess;
}
实现很简单,self()方法就是一个简单的单例调用new 创建了一个ProcessState对象。那看一下ProcessState的构造方法都做了些什么:
…/frameworks/native/libs/binder/ProcessState.cpp
ProcessState::ProcessState()
: mDriverFD(open_driver()) //打开Binder
, mVMStart(MAP_FAILED) //映射内存的的起始地址
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
#if !defined(HAVE_WIN32_IPC)
//为Binder分配一块内存用于存取数据
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE(“Using /dev/binder failed: unable to mmap transaction memory.\n”);
close(mDriverFD);
mDriverFD = -1;
}
#else
mDriverFD = -1;
#endif
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, “Binder driver could not be opened. Terminating.”);
}
在ProcessState的构造函数中首先调用了open_driver()方法初始化了一个ProcessState的变量mDriverFD,这个open_driver()方法很重要,它打开/dev/binder这个虚拟设备为binder通信做准备。在打开binder设备后又调用系统函数mmap() 为打开的binder设备在内存中映射了一块内存空间并将内存地址返回给变量mVMStart。
那先看一下open_driver()是怎么样打开binder驱动设备的。
…/frameworks/native/libs/binder/ProcessState.cpp
static int open_driver()
{
//打开/dev/binder虚拟设备
int fd = open(“/dev/binder”, O_RDWR);
“““““““““““`
//通过ioctl()告诉驱动*多支持的线程数 15
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
return fd;
}
在open_driver()中直接调用了linux系统函数open()打开了/dev/binder设备并为启动的Binder虚拟设备通过ioctl()[系统函数]为binder 设备指定了*大线程数;
分析到这里基本上就是main_mediaserver–>main()函数中sp proc(ProcessState::self())这句代码做的事情。总结起来主要做了两件事情:
open_driver()打开/dev/binder虚拟设备驱动
为打开的Binder虚拟设备分配内存映射空间
那下边继续回到main_mediaserver的main()方法中继续分析,看在获取到ProcessState后的sp sm =defaultServiceManager()干了什么。
defaultServerManager
defaultServerManager()函数会返回一个实现了IServerManager接口的对象,通过这个对象我们可以和另外一个进程的ServerManager进行通信.先看一下defaultServerManager()方法都干了点什么:
…/frameworks/native/libs/binder/IServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
//gDefaultServiceManager对象创建的地方
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
这个方法在IServerManager.cpp中定义的,这个方法又是一个单例来获取一个IServerManger对象。内容很简单但是当我看到interface_cast(…)后我感觉一点都不好,但是它是很重要的不过暂时先不管它。先看看ProcessState::self()->getContextObject(NULL)方法都干了点什么:
…/frameworks/native/libs/binder/ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
//好吧,这里直接调用了getStrongProxyForHande()方法。
//但是传入的参数 0很重要
return getStrongProxyForHandle(0);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
//资源查找,找不到会创建一个新的对象
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
//新创建的binder 一定为空
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
························
Parcel data;
//这里是一次IPC的binder通信过程,暂时不分析
//我们现在分析的是getStrongProxyForHander()方法返回的是什么
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
//创建一个BpBinder对象
b = new BpBinder(handle);
e->binder = b; //填充
if (b) e->refs = b->getWeakRefs();
result = b;
···············
}
return result;
}
在getStrongProxyForHandle()函数中首先调用了lookupHandleLocked(0)方法获取一个handle_entry 类型的结构指针。lookupHandleLocked()就是在一个Vector中查找对象找不到就创建一个,不重要先忽略。然后这里创建了一个BpBinder对象,根据名字看应该是和Binder机制有关的我们先可以一下BpBinder的构造方法:
…/frameworks/native/libs/binder/BpBinder.cpp
//BpBinder构造函数
BpBinder::BpBinder(int32_t handle)
: mHandle(handle) //handle 为 0
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
“““““““`
//另外一个重要对象?
IPCThreadState::self()->incWeakHandle(handle);
}
在BpBinder的构造函数中出现了一个新对象IPCThreadState,对象名字竟然以IPC应该是和Binder的跨进程通信又关系的。
…/frameworks/native/libs/binder/IPCThreadState.cpp
IPCThreadState* IPCThreadState::self()
{
if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;
//TLS = thread location storage 线程本地空间 是线程独有空间
//getSpecific()和setSpecific()可以操作这部分空间
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
//返回一个创建的IPCThreadState对象
return new IPCThreadState;
}
if (gShutdown) return NULL;
““““
goto restart;
}
当我*次看到这个方法时还是有点震惊的,我虽然没有学习过C++但是大一那会儿学习过C语言。当时老师就告诉我们尽量少用goto这个逻辑跳转。这里竟然用了。
这个方法中IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k)是从线程的TLS中获取一个IPCThreadState对象指针,*次调用市肯定是不存在这个对象的所以会new 一个IPCThreadState对象。
TLS是操作系统为每个线程都单独分配的一块内存空间,当前线程独占其他线程无法访问。所以在多线程下对它的访问的线程安全的。
既然这里调用了IPCThreadState的构造函数我们就看看它长什么样子:
…/frameworks/native/libs/binder/IPCThreadState.cpp
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()), //获取上边我们创建的ProcessState对象
mMyThreadId(gettid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
//在构造函数中将自己设置到TLS中
pthread_setspecific(gTLS, this);
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
IPCThreadState的构造函数很简单就是创建自己后将自己设置到当前线程的TLS中,下次就可以直接从当前线程的TLS中获取了。
我们分析了这么多其实都是gDefaultServiceManager = interface_cast(ProcessState::self()->getContextObject(NULL))的getContextObject(null)方法开始分析。好吧,要不是不是回到看一下我都已经不知道自己现在在分析什么了。那现在我们知道了getContextObject()返回的是一个BpBinder对象。那我们再看看interface_cast()设个什么东西:
…/frameworks/native/include/binder/IInterface.h
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
原来interface_cast()是一个定义在IInterface.h头文件中的模范方法,那我们现在根据我们上边的调用翻译一下这个模版方法现在的样子:
inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj) {
return IServiceManager::asInterface(obj);
}
实话说分析到这里我有点懵了不知道怎么分析了. 既然模版方法中调用了IServiceManager::asInterface()方法我们就先看看IServiceManager接口的内容:
…/frameworks/native/include/binder/IServiceManager.h
class IServiceManager : public IInterface
{
public:
//这个鸿定义在IInterface.h中,他主要做了如下工作
//1.定义了一个描述字符串
//2.定义了一个asInterface函数
//3.定义了一个getInterfaceDescriptor函数用于返回上边定义的描述字符串
//4.定义了构造函数和析构函数
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,
};
};
我们都知道Android系统中的系统服务像AMS、WMS等都是有ServiceManager统一管理的。这里的IServiceManager.h就是定义了他的功能接口。在这个接口定义中我们看到一个宏DECLARE_META_INTERFACE(ServiceManager)的使用,那我们先分析一下这个宏定义是什么样子:
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp<I##INTERFACE> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE();
同样我还是先翻译一下这个宏在当前使用场景的样子:
static const android::String16 descriptor;
static android::sp<IServiceManager> asInterface(const android::sp<IBinder>& obj);
virtual const android::String16 getInterfaceDescriptor() const;
IServiceManager();
virtual ~IServiceManager();
从对DECLARE_META_INTERFACE宏的翻译可以看出这是属性和方法的声明;
通过上边的对那个IServiceManager.h和对DECLARE_META_INTERFACE的翻译我们已经知道了IServiceManager接口定义的样子我们下面看一下他的具体实现,但是具体实现内容比较多我抽取其中重要部分分析一下:
…/frameworks/native/libs/binder/IServiceManager.cpp
…………省略………….
//IMPLEMENT_META_INTERFACE这个宏是定义在IInterface.h文件中的
//1.定义常量字符串android.os.IServiceManager
//2.实现getInterfaceDescriptor()函数
//3.实现asInterface()函数,并返回一个BpServiceManager对象
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) {
………..继续省略…………..
}
}
在IServiceManager的实现中真正让我感兴趣的这个IMPLEMENT_META_INTERFACE 宏的使用。同样我们找找这个宏的定义并将这个宏翻译一下:
宏定义在IInterface.h文件中
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const android::sp<android::IBinder>& obj) \
{ \
android::sp<I##INTERFACE> intr; \
if (obj != NULL) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
感觉当前这个宏的使用场景翻译一下:
const android::String16 IServiceManager::descriptor(“android.os.IServiceManager”);
const android::String16& IServiceManager::getInterfaceDescriptor() const {
return IServiceManager::descriptor;
}
android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj) {
android::sp<IBinder> intr;
if(obj != null) {
//这里也很重要
intr = static_cast<IServiceManager>(obj->queryLocalInterface(IServicManager:;descriptor).get());
if(intr == NULL) {
//重点看这里
intr = new BpServieceManager(obj);
}
}
return intr;
//构造函数我就不翻译了。这翻译真要命
}
现在我们已经翻译完了***IMPLEMENT_META_INTERFACE***宏的内容现在将翻译后内容替换到IServiceManager.cpp中看看
…/frameworks/native/libs/binder/IServiceManager.cpp
…………省略………….
//IMPLEMENT_META_INTERFACE这个宏是定义在IInterface.h文件中的
//1.定义常量字符串android.os.IServiceManager
//2.实现getInterfaceDescriptor()函数
//3.实现asInterface()函数,并返回一个BpServiceManager对象
<!–IMPLEMENT_META_INTERFACE(ServiceManager, “android.os.IServiceManager”);–>
const android::String16 IServiceManager::descriptor(“android.os.IServiceManager”);
const android::String16& IServiceManager::getInterfaceDescriptor() const {
return IServiceManager::descriptor;
}
android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj) {
android::sp<IBinder> intr;
if(obj != null) {
//这里也很重要
intr = static_cast<IServiceManager>(obj->queryLocalInterface(IServicManager:;descriptor).get());
if(intr == NULL) {
//重点看这里
intr = new BpServieceManager(obj);
}
}
return intr;
//构造函数我就不翻译了。这翻译真要命
status_t BnServiceManager::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
//printf(“ServiceManager received: “); data.print();
switch(code) {
………..继续省略…………..
}
}
这就是翻译后的IServiceManager.cpp的样子我们重点看一下asInterface()方法, 这里这个方法竟然返回了一个BpServiceManager对象。还记得我们先变分析中哪里调用了这个asInterface()方法吗?没错就是我们在interface_cast()模版方法调用,现在我们知道在当前分析场景下interface_cast()返回的是一个***BpServiceManager***类型的对象。那么问题现在有来了,还记得interface_cast()方法是在哪里调用的吗?没错就是defaultServiceManager()方法中调用的。
现在终于将defaultServiceManager()函数分析完了,*终这个方法会返回一个BpServiceManager类型的对象(累死人了,分析了这么多终于知道了这个方法返回了什么。要疯了,特别想爆粗口)。那现在我是特别想知道BpServiceManager到底是个什么东西。但是现在不着急,defautServiceManager()方法引发这么多的联动分析我还是先回味一下defaultServiceManager()函数都干了些啥:
首先调用了ProcessState::getContextObject(null)函数,但是这个函数什么都没有干就直接调用了自己的getStrongProxyForHandle(0)函数。在getStrongProxyForHandle()函数中创建了一个BpBinder对象。
在BpBinder构造函数中又引出了一个重要的类IPCThreadState类。在这里调用了IPCThreadState::self();
在IPCThreadState::self()函数中首先从线程的TLS中获取IPCThreadState对象。到那时在首次点用时TLS中并未存储,所以会调用它的构造方法创建一个IPCThreadState对象并将创建的对象保存到TLS中。以后就可以直接从TLS中获取。
interface_cast()模版方法中调用了IServiceManager的asInterface()函数。通过我们对模版方法、DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE宏的分析翻译知道*终asInterface()返回了一个BpServiceManager对象。
在整个defaultServiceManager()函数中涉及到BpBinder、ProcessState、IPCThreadState、BpServiceManager等新的类。我们有必要分析一下目前他们的关系如何。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8YrAU0q2-1593588562795)(https://thumbnail0.baidupcs.com/thumbnail/bb7c4d396ec292dc71350f5750f7c4d5?fid=2586003311-250528-448513258459521&time=1546952400&rt=sh&sign=FDTAER-DCb740ccc5511e5e8fedcff06b081203-HxxYlrpgwgJNMNKaDwPEh57%2BXOk%3D&expires=8h&chkv=0&chkbd=0&chkpc=&dp-logid=183401465543768111&dp-callid=0&size=c710_u400&quality=100&vuk=-&ft=video)]
现在我们可以根据类图关系再来分析一下他们。首先看一下BpServiceManager:
class BpServiceManager : public BpInterface<IServiceManager>
{
//impl参数是IBinder类型,实际上就是上边创建的BpBinder
public BpServiceManager(const sp<IBinder>& impl)
//调用了父类的构造方法,参数impl 是 BpBinder
: BpInterface<IServiceManager>(impl)
{
}
}
BpServiceManager继承自BpInterface。现在看一下BpInterface:
模版类
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
—————————-
模版方法
template<typename INTERFACE>
//remote参数是BpBinder
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
//调用父类的构造方法
: BpRefBase(remote)
{
}
继续看一下BpRefBase的实现:
//mRemote*终等于BpBinder(0)对象
BpRefBase::BpRefBase(const sp<IBinder>& o)
//重点在这里,Bpbinder本传递给了mRemote.Binder的通信需要通过mRemote来完成。
: mRemote(o.get()), mRefs(NULL), mState(0)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
if (mRemote) {
mRemote->incStrong(this); // Removed on first IncStrong().
mRefs = mRemote->createWeak(this); // Held for our entire lifetime.
}
}
现在我们知道BpServiceManager实现了IServiceManager接口同时持有了BpBinder,BpBinder可以用于进程的通信。此时BpServiceManager是ServiceManager客户端的代理对象,BpBinder是Binder通信机制的Client端代表。
2. MediaPlayerService addService()
我们继续回到MediaServer的main()函数中继续分析。看看MediaPlayerService::instantiate()实现:
void MediaPlayerService::instantiate() {
//通过上边的分析我们已经知道defaultServiceManager()返回的是一个BpServiceManager对象。在这里调用了他的addService()方法。
defaultServiceManager()->addService(
String16(“media.player”), new MediaPlayerService());
}
在instantiate()函数中调用了BpServiceManager的addService():
…/frameworks/native/libs/binder/IServiceManager.cpp的内嵌类BpServiceManager
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);
//remote()函数返回的是mRemote,就是BpRefBase中的mRemote,即BpBinder对象。这里调用了BpBinder的transact()方法。
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
从BpServiceManager的addService()方法可以看出*终将调用转移到了BpBinder中。由此我们知道BpBinder才是代表client进行跨进程通信的代表。下面我们继续分析一下BpBinder;
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
//BpBinder将通信委托给了IPCThreadState的transcat()方法
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
看到这里还是有点震惊的,我本来认为BpBinder已经是实现通信的客户端的代表了。现在发现它竟然将通信委托给IPCThreadState来完成。原来BpBinder还是个壳子。继续看一下IPCThreadState::transact():
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
status_t err = data.errorCheck();
““““““““““““““`
if (err == NO_ERROR) {
LOG_ONEWAY(“>>>> SEND from pid %d uid %d %s”, getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ? “READ REPLY” : “ONE WAY”);
//发送Binder通信消息
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
#if 0
if (code == 4) { // relayout
ALOGI(“>>>>>> CALLING transaction 4”);
} else {
ALOGI(“>>>>>> CALLING transaction %d”, code);
}
#endif
if (reply) {
//等待通讯结果
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
““““““““““““
} else {
err = waitForResponse(NULL, NULL);
}
return err;
}
在IPCThreadState的transact()方法中有两个重要的方法调用, err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL)和err = waitForResponse(reply)。我们先来分析一下writeTransactionData()的实现:
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
binder_transaction_data tr; //binder_transaction_data 是binder通信的数据结构
tr.target.ptr = 0; /* Don’t pass uninitialized stack data to a remote process */
tr.target.handle = handle; //现在handle是0;0代表ServiceManager。
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
tr.data.ptr.offsets = data.ipcObjects();
} else if (statusBuffer) {
tr.flags |= TF_STATUS_CODE;
*statusBuffer = err;
tr.data_size = sizeof(status_t);
tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
tr.offsets_size = 0;
tr.data.ptr.offsets = 0;
} else {
return (mLastError = err);
}
//mOut的类型是Pracel.它是准备发送给Binder的Server端。
mOut.writeInt32(cmd);
//将Binder通信的数据写入到mOut中
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
从writeTransactionData()方法的分析发现里边主要做了数据准备并将数据序列化到Pracel中。
我们继续分析分析waitForResponse(reply)函数:
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
//循环处理
while (1) {
//重点talkWithDriver()
if ((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
IF_LOG_COMMANDS() {
alog << “Processing waitForResponse Command: ”
<< getReturnString(cmd) << endl;
}
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
break;
case BR_DEAD_REPLY:
err = DEAD_OBJECT;
goto finish;
case BR_FAILED_REPLY:
err = FAILED_TRANSACTION;
goto finish;
case BR_ACQUIRE_RESULT:
{
ALOG_ASSERT(acquireResult != NULL, “Unexpected brACQUIRE_RESULT”);
const int32_t result = mIn.readInt32();
if (!acquireResult) continue;
*acquireResult = result ? NO_ERROR : INVALID_OPERATION;
}
goto finish;
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
ALOG_ASSERT(err == NO_ERROR, “Not enough command data for brREPLY”);
if (err != NO_ERROR) goto finish;
if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer, this);
} else {
err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
}
} else {
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
continue;
}
}
goto finish;
default:
//重点
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
BR_开头的case都是Binder Server端的,BC_开头的case是Binder Client端使用。
在IPCThreadState的waitForResponse()函数中重要的方法有talkWithDriver()和case 的default:分支中的executeCommand()函数。现在我们先分析一下talkWithDriver():
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
if (mProcess->mDriverFD <= 0) {
return -EBADF;
}
binder_write_read bwr; //binder通信的数据结构
// Is the read buffer empty?
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
// We don’t want to write anything if we are still reading
// from data left in the input buffer and the caller
// has requested to read the next data.
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();
// This is what we’ll read.
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
IF_LOG_COMMANDS() {
TextOutput::Bundle _b(alog);
if (outAvail != 0) {
alog << “Sending commands to driver: ” << indent;
const void* cmds = (const void*)bwr.write_buffer;
const void* end = ((const uint8_t*)cmds)+bwr.write_size;
alog << HexDump(cmds, bwr.write_size) << endl;
while (cmds < end) cmds = printCommand(alog, cmds);
alog << dedent;
}
alog << “Size of receive buffer: ” << bwr.read_size
<< “, needRead: ” << needRead << “, doReceive: ” << doReceive << endl;
}
// Return immediately if there is nothing to do.
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
//又是一个循环
do {
IF_LOG_COMMANDS() {
alog << “About to read/write, write size = ” << mOut.dataSize() << endl;
}
#if defined(HAVE_ANDROID_OS)
//通过ioctl()进行读写
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
if (mProcess->mDriverFD <= 0) {
err = -EBADF;
}
IF_LOG_COMMANDS() {
alog << “Finished read/write, write size = ” << mOut.dataSize() << endl;
}
} while (err == -EINTR);
IF_LOG_COMMANDS() {
alog << “Our err: ” << (void*)(intptr_t)err << “, write consumed: ”
<< bwr.write_consumed << ” (of ” << mOut.dataSize()
<< “), read consumed: ” << bwr.read_consumed << endl;
}
if (err >= NO_ERROR) {
//清空客户端的Pracel的内存空间
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
else
mOut.setDataSize(0);
}
//将ioctl()从sever端获取的数据写入到mIn中准备发送给client端
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
““““““
return NO_ERROR;
}
return err;
}
完成Binder通信其实是通过Binder驱动的共享内存来完成不同进程之间的通信,从对talkWithDriver()函数分析来看完成对Binder驱动的共享内存的操作是ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)函数来完成的。ioctl()是一个linux系统API。对ioctl()方法调用是在do{}while()中调用的,由此可见这个ioctl()会多次调用来完成通信。在ioctl()完成后请求结果被放到binder_write_read类型的bwr中,然后将bwr的结果内容写入到Pracel的mIn中为下一步返回客户端做做准备。
我们在回到IPCThreadState::waitForResponse()函数中分析一下另外一个executeCommand(cmd)方法:
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch ((uint32_t)cmd) {
case BR_ERROR:
result = mIn.readInt32();
break;
case BR_OK:
break;
case BR_ACQUIRE:
“““““`
break;
case BR_RELEASE:
“““““`
break;
case BR_INCREFS:
““““““`
break;
““““`
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
ALOG_ASSERT(result == NO_ERROR,
“Not enough command data for brTRANSACTION”);
if (result != NO_ERROR) break;
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);
const pid_t origPid = mCallingPid;
const uid_t origUid = mCallingUid;
const int32_t origStrictModePolicy = mStrictModePolicy;
const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;
mCallingPid = tr.sender_pid;
mCallingUid = tr.sender_euid;
mLastTransactionBinderFlags = tr.flags;
int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
if (gDisableBackgroundScheduling) {
if (curPrio > ANDROID_PRIORITY_NORMAL) {
setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
}
} else {
if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
set_sched_policy(mMyThreadId, SP_BACKGROUND);
}
}
Parcel reply;
status_t error;
if (tr.target.ptr) {
//BnService从BBinder派生
//这里的B实际上实现了BnServiceXXX的对象
sp<BBinder> b((BBinder*)tr.cookie);
error = b->transact(tr.code, buffer, &reply, tr.flags);
} else {
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
if ((tr.flags & TF_ONE_WAY) == 0) {
LOG_ONEWAY(“Sending reply to %d!”, mCallingPid);
if (error < NO_ERROR) reply.setError(error);
sendReply(reply, 0);
} else {
LOG_ONEWAY(“NOT sending reply to %d!”, mCallingPid);
}
mCallingPid = origPid;
mCallingUid = origUid;
mStrictModePolicy = origStrictModePolicy;
mLastTransactionBinderFlags = origTransactionBinderFlags;
}
break;
·····································
return result;
}
看到executeCommand()函数中那么多的switch分支真不知道从哪里分析,脑子已经懵懵的。还是从BR_TRANSACTION:这个分支看看吧。在这个分支中我们可以看到//BnService从BBinder派生sp b((BBinder*)tr.cookie);error = b->transact(tr.code, buffer, &reply, tr.flags);我们又看到了一个BBinder类的对象,有我们从BpBinder是Binder Client的代表可以猜测BBinder可能是Binder的Server端的代表。实际上这里的b是BnSerciceManager对象。那先放下executeCommaond()函数,这里我们先来分析一下BBinder和BnServiceManaer是什么然后在回来分析:
“`/frameworks/native/include/binder/IServiceManager.h
class BnServiceManager : public BnInterface<IServiceManager>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
开始看张类图直观一些,手画丑的不行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2YzuoKT4-1593588562797)(https://thumbnail0.baidupcs.com/thumbnail/01a427c58cc69e8688aeddecc50fb5c3?fid=2586003311-250528-868147785755165&time=1546952400&rt=sh&sign=FDTAER-DCb740ccc5511e5e8fedcff06b081203-AvZaBr10el8zdroFSH1cY0BrMYs%3D&expires=8h&chkv=0&chkbd=0&chkpc=&dp-logid=183456904394929954&dp-callid=0&size=c710_u400&quality=100&vuk=-&ft=video)]
BnServiceManager继承自BnInterface,再看一下BnInterface是什么:
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
BnInterface是个模版类继承自BBinder,在BnServiceManager继承BnInterface时模版类中的INTERFACE 是 IServiceManager。用于BnInterface继承了INTERFACE,所以BnServicManager继承了ISeviceManager接口。下面看一下BBinder的定义:
“`/frameworks/native/include/binder/Binder.h
class BBinder : public IBinder
{
………….
}
这样以来继承关系已经很明确。再BnServiceManager的接口声明中重新声明了onTransact()函数并在IServiceManager.cpp中实现了它:
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: {
········
} break;
case CHECK_SERVICE_TRANSACTION: {
········
} break;
case ADD_SERVICE_TRANSACTION: {
CHECK_INTERFACE(IServiceManager, data, reply);
String16 which = data.readString16();
sp<IBinder> b = data.readStrongBinder();
//在这里有调用了addService()完成真正的服务添加。
status_t err = addService(which, b);
reply->writeInt32(err);
return NO_ERROR;
} break;
case LIST_SERVICES_TRANSACTION: {
········
return NO_ERROR;
} break;
default:
//调用父类默认实现
return BBinder::onTransact(code, data, reply, flags);
}
}
我们对BnServiceManager和BBinder的分析先分析到这里,回到executeCommond()方法中再结合sp b((BBinder*)tr.cookie);error = b->transact(tr.code, buffer, &reply,tr.flags);调用bnServiceManager的transact()方法。以分析的addService()*终会进入到case ADD_SERVICE_TRANSACTION:分支当中并在这里调用了addService()方法。
***看到这里我是有点模糊的这个分支中的addService()方法的实现在哪里,也没有找到一个类继承自BnServiceManager。***后来网上看别人的分析发现还是有个文件实现了这里的ServiceManager的功能,具体实现在Service_manager.c中实现的。
不太明白为什么不继续继承BnServiceManager来实现具体逻辑呢?
ServiceManager
ServiceManager的实现在Service_manager.c中,先从这个文件的main()函数开始了解一下它干了啥:
int main(int argc, char **argv)
{
struct binder_state *bs;
//打开binder虚拟设备
bs = binder_open(128*1024);
if (!bs) {
ALOGE(“failed to open binder driver\n”);
return -1;
}
//角色转换
if (binder_become_context_manager(bs)) {
ALOGE(“cannot become context manager (%s)\n”, strerror(errno));
return -1;
}
//重点,处理客户端发过来的请求
binder_loop(bs, svcmgr_handler);
return 0;
}
main()函数比较简单主要通过调用了binder_open()函数打开Binder的虚拟设备.先看一下binder_open()都做了些什么:
/打开Binder设备
struct binder_state *binder_open(size_t mapsize)
{
struct binder_state *bs;
struct binder_version vers;
bs = malloc(sizeof(*bs));
if (!bs) {
errno = ENOMEM;
return NULL;
}
//打开虚拟设备,调用Linux系统方法打开文件
bs->fd = open(“/dev/binder”, O_RDWR);
if (bs->fd < 0) {
fprintf(stderr,”binder: cannot open device (%s)\n”,
strerror(errno));
goto fail_open;
}
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
fprintf(stderr,
“binder: kernel driver version (%d) differs from user space version (%d)\n”,
vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
goto fail_open;
}
bs->mapsize = mapsize;
//调用mmap()函数给binder驱动做内存映射
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
if (bs->mapped == MAP_FAILED) {
fprintf(stderr,”binder: cannot map device (%s)\n”,
strerror(errno));
goto fail_map;
}
return bs;
fail_map:
close(bs->fd);
fail_open:
free(bs);
return NULL;
}
我在这个方法中又看到了goto的使用。有点兴奋!
在open_binder()函数中打开了Binder驱动,并给起映射了内存空间。我们继续看一下binder_become_context_manager(bs)干了什么:
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
很简单但是我没有看太懂,主要是对ioctl()这个函数不太懂。大概是给打开的Binder设备指定了映射名称为0;(谁懂给我普及一下)
ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的参数个数如下:int ioctl(int fd, int cmd, …);其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般*多一个,有或没有是和cmd的意义相关的。ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就能在用户程序中使用ioctl函数控制设备的I/O通道。百度百科
还有一个处理Binder请求的方法binder_loop(bs, svcmgr_handler):
//binder_handler 是个函数指针,func现在是svcmgr_handler
void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
struct binder_write_read bwr;
uint32_t readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER;
//在binder_write中调用了ioctl函数,调用Binder设备的函数,标志serviceManager进入的Loop 状态。
binder_write(bs, readbuf, sizeof(uint32_t));
//循环不断的
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (uintptr_t) readbuf;
//通过ioctl()方法从Binder设备中读取缓冲区,检查是不是又IPC请求。
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < 0) {
ALOGE(“binder_loop: ioctl failed (%s)\n”, strerror(errno));
break;
}
//接受到请求,然后解析结果 调用func函数
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
if (res == 0) {
ALOGE(“binder_loop: unexpected reply?!\n”);
break;
}
if (res < 0) {
ALOGE(“binder_loop: io error %d %s\n”, res, strerror(errno));
break;
}
}
}
在binder_loop()中让binder设备进入loop状态,通过循环不断通过ioctl()方法获取Binder设备是不是有IPC请求,如果有将获取到的数据交给binder_parse()函数进行解析.
int binder_parse(struct binder_state *bs, struct binder_io *bio,
uintptr_t ptr, size_t size, binder_handler func)
{
……………..数据处理………………………..
case BR_TRANSACTION: {
………………..
if (func) {
unsigned rdata[256/4];
struct binder_io msg;
struct binder_io reply;
int res;
bio_init(&reply, rdata, sizeof(rdata), 4);
bio_init_from_txn(&msg, txn);
//调用了func()函数,有func()函数去做真正的服务管理
res = func(bs, txn, &msg, &reply);
binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
}
ptr += sizeof(*txn);
break;
}
……………………………..
}
}
return r;
}
在binder_prase()方法的binder_handler func参数指向的是svcmgr_handler函数,下面看看这个函数:
…/frameworks/native/cmds/servicemanager/service_manager.c
//binder 通信处理数据的回调函数
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int allow_isolated;
//ALOGI(“target=%p code=%d pid=%d uid=%d\n”,
// (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
if (txn->target.ptr != BINDER_SERVICE_MANAGER)
return -1;
if (txn->code == PING_TRANSACTION)
return 0;
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,”invalid id %s\n”, str8(s, len));
return -1;
}
if (sehandle && selinux_status_updated() > 0) {
struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
if (tmp_sehandle) {
selabel_close(sehandle);
sehandle = tmp_sehandle;
}
}
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
……….
case SVC_MGR_ADD_SERVICE:
//注册服务
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
//注册服务真正工作的地方
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
case SVC_MGR_LIST_SERVICES: {
……
}
default:
ALOGE(“unknown code %d\n”, txn->code);
return -1;
}
bio_put_uint32(reply, 0);
return 0;
}
在svcmgr_handler()函数中SVC_ADD_SERVICES分支中注册服务,其中注册服务的实际处理交给了do_add_service()方法继续处理。
int do_add_service(struct binder_state *bs,
const uint16_t *s, size_t len,
uint32_t handle, uid_t uid, int allow_isolated,
pid_t spid)
{
struct svcinfo *si;
if (!handle || (len == 0) || (len > 127))
return -1;
//验证UID是否有添加服务的权限。
if (!svc_can_register(s, len, spid)) {
ALOGE(“add_service(‘%s’,%x) uid=%d – PERMISSION DENIED\n”,
str8(s, len), handle, uid);
return -1;
}
//检查服务是不是已经注册
si = find_svc(s, len);
if (si) {
if (si->handle) {
ALOGE(“add_service(‘%s’,%x) uid=%d – ALREADY REGISTERED, OVERRIDE\n”,
str8(s, len), handle, uid);
svcinfo_death(bs, si);
}
si->handle = handle;
} else {
//如果没有注册分配内存
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
//si这个结构体
si->handle = handle;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
si->name[len] = ‘\0’;
si->death.func = (void*) svcinfo_death;
si->death.ptr = si;
si->allow_isolated = allow_isolated;
si->next = svclist;
//插入链表
svclist = si;
}
binder_acquire(bs, handle);
binder_link_to_death(bs, handle, &si->death);
return 0;
}
//存储注册服务的结构体,是个链表结构
struct svcinfo
{
struct svcinfo *next;
uint32_t handle;
struct binder_death death;
int allow_isolated;
size_t len;
uint16_t name[0];
};
do_add_service()方法通过坚定要注册的服务是否有权限被注册,然后再检查服务是否已经注册了,如果没有被注册则将其插入到链表中。这样我们的服务注册工作已经完成。
C++层的Binder通信的分析基本上分析完了。想抽时间再分析一下Java层对c++层的封装。