一 概述
我们知道在 Android 系统中,无论是 Server 端进程注册服务 (addService) 或者是 Client 端进程获取服务 (getService) ,都需要获取 SMgr 的 Binder 代理,通过 SMgr 的 Binder 代理接口来调用相关函数进而实现相关操作,但是该如何获取呢?我们在系列3中只是分析了 SMgr 的启动和工作机制,并没有阐述其它进程是如何获取 SMgr 接口的,在本篇文章中将讨论这个问题.
在源码中可以看到其它进程都是通过 IServiceManager 的 defaultServiceManager() 方法来完成对 SMgr代理接口的获取,我们来看代码如下:
framework/native/libs/binder/IServiceManager.cpp
1.1 入口函数 defaultServiceManager
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;
}
获取 SMgr 对象采用单例模式,当 gDefaultServiceManager 存在,则直接返回,否则创建一个新对象。 发现与一般的单例模式不太一样,里面多了一层while循环,这个是因为当创建 gDefaultServiceManager 时,SMgr 所在进程可能尚未准备就绪,这时通过sleep 1秒后,循环尝试获取直到成功。gDefaultServiceManager 的创建过程,可分解为以下3个部分:
- ProcessState::self():用于获取 ProcessState 对象,也是单例模式,这个之前讲过,每个进程有且只有一个ProcessState 对象,存在则直接返回,不存在则创建
- getContextObject(null): 用于获取 BpBinder 对象,我们已经知道 SMgr 对应的句柄值为0
- interface_cast<IServiceManage>:用于获取BpServiceManager对象
接下来详细分析
二 获取ProcessState对象
2.1 ProcessState::self()
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;//存在则返回,不存在则创建
}
gProcess = new ProcessState("/dev/binder");//直接new出来
return gProcess;
}
ProcessState在创建的过程中会执行打开Binder驱动,并调用mmap函数建立内存映射等相关操作.
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))//打开Binder驱动,这个driver参数为"/dev/binder"
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
//调用mmap函数建立内存映射
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;
mDriverName.clear();
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
我们知道每个进程有且只有一个 ProcessState 对象,这个也是设计为单例模式的原因,在 ProcessState 的构造方法中会调用 open_driver 函数打开Binder驱动,并把打开驱动之后的文件描述符 fd 赋值给了 mDriverFD,并调用mmap函数建立内存映射,需要注意的是映射空间的大小 BINDER_VM_SIZE,这个值为(1*1024*1024) - (4096 *2),也就是Binder分配的默认内存大小为1M-8k.
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);//打开Binder驱动"/dev/binder"
if (fd >= 0) {
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers);//调用ioctl函数查看Binder驱动版本
........
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;//这个值为15
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);//通过ioctl设置Binder驱动支持的最大线程数
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
return fd;
}
可以看到 open_driver 的主要作用是打开 “/dev/binder” 设备,并设定Binder驱动支持的最大线程数为15.
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
#define DEFAULT_MAX_BINDER_THREADS 15
三 获取BpBinder对象
3.1 getContextObject
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
3.2 getStrongProxyForHandle(0)
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
//根据句柄值查询handle_entry,这个handle_entry里的binder就是句柄值对应的BpBinder对象
//这个handle_entry我们在系列2中讲述ProcessState的时候已经讲过
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {//如果句柄值为0
Parcel data;
//通过ping操作测试Binder是否准备就绪
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
b = new BpBinder(handle); //根据句柄值handle,直接创建BpBinder
e->binder = b;//把创建好的BpBinder赋值给handle_entry的binder域
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
先调用lookupHandleLocked函数根据句柄值在mHandleToObject中查询对应的handle_entry,其中handle_entry里的binder就是句柄值对应的BpBinder对象
3.3 lookupHandleLocked
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
const size_t N=mHandleToObject.size();
if (N <= (size_t)handle) {
handle_entry e;
e.binder = NULL;
e.refs = NULL;
status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
if (err < NO_ERROR) return NULL;
}
return &mHandleToObject.editItemAt(handle);
}
在lookupHandleLocked函数中,主要是针对向量表mHandleToObject的操作,查询与句柄值对应的handle_entry,如果不存在的话就创建然后插入到这个向量表中,如果存在的话就返回.这个向量表mHandleToObject在系列2中介绍ProcessState的时候已经讲过,大家可以回顾下.在某个进程获取SMgr之前,这个mHandleToObject中的handle_entry项的个数为0,所以执行到的这里时候会生成一个handle_entry,并插入到mHandleToObject中,然后返回这个handle_entry.
接下来继续回到getStrongProxyForHandle函数中,可以看到会走到b == NULL分支,然后生成一个句柄值为0的BpBinder对象并返回.
四 获取BpServiceManager
4.1 interface_cast
这个在系列2中已经介绍过,代码如下:
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
最终调用的是asInterface函数,在系列2中我们讲述DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE模板的时候已经介绍过了,大家回顾下,结果就是通过这些模板new 了一个BpServiceManager出来,并把这个BpBinder作为参数传递到BpServiceManager中,BpServiceManager的构造方法代码如下:
explicit BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)//这里的impl就是新创建的BpBinder
{
}
BpServiceManager继承自BpInterface
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
explicit BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
BpInterface又继承自BpRefBase,BpRefBase类的定义如下:
class BpRefBase : public virtual RefBase
{
protected:
explicit BpRefBase(const sp<IBinder>& o);
virtual ~BpRefBase();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
inline IBinder* remote() { return mRemote; }
inline IBinder* remote() const { return mRemote; }
private:
BpRefBase(const BpRefBase& o);
BpRefBase& operator=(const BpRefBase& o);
IBinder* const mRemote;
RefBase::weakref_type* mRefs;
std::atomic<int32_t> mState;
};
BpRefBase的构造函数
BpRefBase::BpRefBase(const sp<IBinder>& o)
: 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.
}
}
这里的impl就是我们创建的BpBinder对象,我们知道BpXXXX继承自BpInterface<IXXXX>,而BpInterface又继承自BpRefBase,我们再看BpRefBase的构造函数中,把这个BpBinder参数赋值给了mRemote,这个就是我们在系列2中所说的:Client进程并不直接和BpBinder(Binder代理)打交道,而是通过调用BpInterface(接口代理)的成员函数来完成远程调用的,此时,BpBinder已经被聚合进BpInterface了,它在BpInterface内部完成了一切跨进程通信的机制.我们回顾下图加深理解.
我们继续看BpServiceManager是怎么跨进程通信的,代码如下:
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
explicit BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
........
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);//调用remote()通过transact传输
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);//调用remote()通过transact传输
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);//调用remote()通过transact传输
if (err != NO_ERROR)
break;
res.add(reply.readString16());
}
return res;
}
};
可以看到都是通过调用remote()实现跨进程传输的,而根据BpRefBase的定义我们这个这个方法返回的就是mRemote,而这个值就是我们传递过去的BpBinder对象.
五 总结
defaultServiceManager 等价于 new BpServiceManager(new BpBinder(0));
ProcessState::self()主要工作:
调用open(),打开/dev/binder驱动设备;
再利用mmap(),创建大小为1M-8K的内存地址空间;
设定当前进程最大的最大并发Binder线程个数为16。
BpServiceManager巧妙将通信层与业务层逻辑合为一体,
通过继承接口IServiceManager实现了接口中的业务逻辑函数;
通过成员变量mRemote= new BpBinder(0)进行Binder通信工作。
BpBinder通过handler来指向所对应BBinder, 在整个Binder系统中handle=0代表ServiceManager所对应的BBinder。