本文参考《Android系统源代码情景分析》,作者罗升阳。
一、测试代码:
~/Android/external/binder/server
----FregServer.cpp
~/Android/external/binder/common
----IFregService.cpp
----IFregService.h
~/Android/external/binder/client
----FregClient.cpp
Binder库(libbinder)代码:
~/Android/frameworks/base/libs/binder
----BpBinder.cpp
----Parcel.cpp
----ProcessState.cpp
----Binder.cpp
----IInterface.cpp
----IPCThreadState.cpp
----IServiceManager.cpp
----Static.cpp
~/Android/frameworks/base/include/binder
----Binder.h
----BpBinder.h
----IInterface.h
----IPCThreadState.h
----IServiceManager.h
----IBinder.h
----Parcel.h
----ProcessState.h
驱动层代码:
~/Android//kernel/goldfish/drivers/staging/android
----binder.c
----binder.h
二、源码分析
1、程序首先开始从Service进程FregServer.cpp的main函数开始执行
~/Android/external/binder/server
----FregServer.cpp
class FregService : public BnFregService
{
...........
public:
static void instantiate()
{
defaultServiceManager()->addService(String16(FREG_SERVICE), new FregService());
}
...........
};
int main(int argc, char** argv)
{
FregService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
main函数首先调用静态方法instantiate,在instantiate中调用了defaultServiceManager(),因为include #include <binder/IServiceManager.h>,所以可以调用
defaultServiceManager()函数实现如下:
~/Android/frameworks/base/libs/binder
----IServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;//如果已经创建了代理对象,那么就直接返回
{
AutoMutex _l(gDefaultServiceManagerLock);//使用锁,来实现单例模式
if (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(//分三步获取Service Manager代理对象
ProcessState::self()->getContextObject(NULL));
}
}
return gDefaultServiceManager;
}
其中gDefaultServiceManagerLock,gDefaultServiceManager都定义在Static.cpp中。
~/Android/frameworks/base/libs/binder
----Static.cpp
Mutex gDefaultServiceManagerLock; //锁
sp<IServiceManager> gDefaultServiceManager; //IServiceManager的强指针
全局变量
gDefaultServiceManager是一个类型为IServiceManager的强指针,它指向进程内的一个BpServiceManager对象,即Service Manager代理对象;而全局变量gDefaultServiceManagerLock是用来保证一个进程至多只有一个Service Manager代理对象。结合锁机制来保证对象在进程中的唯一性,这是单例设计模式的经典实现。
如果已经创建了代理对象,那么就直接返回。如果没有创建,那么分三步创建:
(1)、调用ProcessState类的静态成员函数self获取进程内的一个ProcessState对象。
(2)、调用前面获得的ProcessState对象的成员函数getContextObject创建一个Binder代理对象
(3)、调用模板函数interface_cast<IServiceManager>将前面获得的Binder代理对象封装成一个Service Manager代理对象。
2、调用ProcessState类的静态成员函数self获取进程内的一个ProcessState对象
~/Android/frameworks/base/libs/binder
----ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
if (gProcess != NULL) return gProcess;//如果已经创建了,就直接返回
AutoMutex _l(gProcessMutex);
if (gProcess == NULL) gProcess = new ProcessState;//创建ProcessState对象
return gProcess;
}
其中gProcess,gProcessMutex都位于Static.cpp中
Mutex gProcessMutex;
sp<ProcessState> gProcess;
全局变量gProcess是一个类型为ProcessState的强指针,它指向进程内的一个ProcessState对象;而全局变量gProcessMutex是一个互斥锁,是用来保证一个进程至多只有一个ProcessState对象的,同样是一个单例模式。
首次进入,故创建ProcessState对象。
~/Android/frameworks/base/libs/binder
----ProcessState.cpp
ProcessState::ProcessState()
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
.....
{
if (mDriverFD >= 0) {
...........
// 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);
...........
}
在初始化构造函数中调用了open_driver方法。
~/Android/frameworks/base/libs/binder
static int open_driver()
{
if (gSingleProcess) {
return -1;
}
int fd = open("/dev/binder", O_RDWR);//又一个进程打开了设备文件,binder_procs又多了一个进程的结构体
if (fd >= 0) {
fcntl(fd, F_SETFD, FD_CLOEXEC);
int vers;
#if defined(HAVE_ANDROID_OS)
status_t result = ioctl(fd, BINDER_VERSION, &vers);//调用ioctl传入BINDER_VERSION参数来获取vers
#else
status_t result = -1;
errno = EPERM;
#endif
if (result == -1) {
LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
LOGE("Binder driver protocol does not match user space protocol!");
close(fd);
fd = -1;
}
#if defined(HAVE_ANDROID_OS)
size_t maxThreads = 15;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);//调用ioctl传入BINDER_SET_MAX_THREADS参数来设备该进程所支持的最大线程数
if (result == -1) {
LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
#endif
} else {
LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
}
return fd;
}
open_driver首先调用了open打开设备文件,在http://blog.csdn.net/jltxgcy/article/details/25797011这盘文章中已经讲解了驱动层的binder_open所做的事。然后的调用ioctl传入BINDER_VERSION参数来获取vers。最后调用ioctl传入BINDER_SET_MAX_THREADS参数来设备该进程所支持的最大线程数。
在初始化列表中调用mmap把设备文件/dev/binder映射到进程的地址空间,其实将/dev/binder映射到进程的地址空间实际上是请求Binder驱动程序为进程分配内核缓冲区。
3、调用前面获得的ProcessState对象的成员函数getContextObject创建一个Binder代理对象
~/Android/frameworks/base/libs/binder
----ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
if (supportsProcesses()) {//为true
return getStrongProxyForHandle(0);
} else {
return getContextObject(String16("default"), caller);
}
}
~/Android/frameworks/base/libs/binder
----ProcessState.cpp
bool ProcessState::supportsProcesses() const
{
return mDriverFD >= 0;
}
由于在open_driver时,mDriverFD已经大于0,所以程序开始执行getStrongProxyForHandle(0)。
~/Android/frameworks/base/libs/binder
----ProcessState.cpp
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);//检查成员变量mHandleToObject是否已经存在一个与句柄值handle对应的handle_entry结构体
if (e != NULL) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {//如果进程尚未为句柄值handle创建过Binder代理对象,或者创建了Binder代理对象但已经销毁了
b = new BpBinder(handle); //Binder代理对象,handle为0
e->binder = b;//保存再e的成员变量binder中
if (b) e->refs = b->getWeakRefs();//将弱引用计数对象保存在e的成员变量refs中
result = b;//返回结果
} else {//如果进程已经创建了Binder代理对象,并且没有销毁,那么直接返回
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn't have one
// but another team is sending the handle to us.
result.force_set(b);//设置返回结果result
e->refs->decWeak(this);//减少弱引用计数,因为attemptIncWeak增加了弱引用计数
}
}
return result;
}
参数handle的值等于0,表示要创建的Binder代理对象的句柄值等于0,即要创建一个Binder代理对象。Binder库为每个进程维护了一个handle_entry类型的Binder代理对象列表,它以句柄值作为关键字来维护进程内部所有的Binder代理对象。这个Binder代理对象列表保存在ProcessState类的成员变量mHandleToObject,它的定义如下:
~/Android/frameworks/base/include/binder
----ProcessState.h
class ProcessState : public virtual RefBase
{
.......
struct handle_entry {
IBinder* binder;//Binder代理对象
RefBase::weakref_type* refs;//一个弱引用计数对象
};
..........
Vector<handle_entry>mHandleToObject;//列表
.........
};
每一个Binder代理对象都使用一个handle_entry结构体来描述。结构体handle_entry的两个成员变量binder和refs分别指向一个Binder代理对象,以及它内部的一个弱引用计数对象。
回到ProcessState类的成员函数getStrongProxyForHandle(0),首先调用成员函数lookupHandleLocked来检查成员变量mHandleToObject是否已经存在一个与句柄值handle对应的handle_entry结构体,它的实现如下:
~/Android/frameworks/base/libs/binder
----ProcessState.cpp
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
const size_t N=mHandleToObject.size();//列表的大小
if (N <= (size_t)handle) {如果句柄值大于或者等于列表大小,否则直接返回指向该结构体的指针
handle_entry e;//创建handle_entry结构体
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);//返回指向该结构体的指针
}
一个Binder代理对象的句柄值同时也是它在列表mHandleToObject中的索引值。首先检查句柄值handle是否大于或者等于列表mHandleToObject的大小,如果是,那么mHandleToObject列表里面就不存在一个与句柄值handle对应的handle_entry结构体,那么创建一个handle_entry结构体,并插入到对应位置,最后返回指向该结构体的指针。
程序继续执行,如果hanle_entry结构体e的成员变量binder的值为NULL,说明进程尚未为句柄值handle创建过Binder代理对象,因此就会根据句柄值handle创建一个Binder代理对象,并且将它保存在handle_entry结构体e的成员变量binder中。并且把弱引用计数对象保存在e的成员变量refs中。
如果hanle_entry结构体e的成员变量binder的值不为NULL,即它已经指向了一个Binder代理对象,就需要继续检查这个Binder代理对象是否还活着,方法是调用它的弱引用计数对象的成员函数attemptIncWeek来尝试增加它的弱引用数。由于Binder代理对象(即BpBinder对象)的生命周期是受弱引用计数控制的,因此如果不能成功增加它的弱引用计数,那么就说明它已经被销毁了。在这种情况下,也需要重新为句柄值handle创建一个Binder代理对象。
如果handle_entry结构体e成员变量binder的值不等于NULL,并且调用它的成员attmptIncWeek能够成功地增加与它对应的一个Binder代理对象的弱引用计数,那么就说明在进程中已经有一个Binder代理对象与句柄值handle相对应,并且这个Binder代理对象是有效的,因此,可以直接将它返回调用调用者。注意函数在将这个Binder代理对象返回给调用者之前,会减少它的弱引用计数,因为attemptIncWeek增加了弱应用计数。
下面我们分析下如何创建Binder代理对象,即new BpBinder(handle)究竟做了什么?
~/Android/frameworks/base/include/binder
----BpBinder.cpp
BpBinder::BpBinder(int32_t handle)
: mHandle(handle)//mHandle等于0
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
LOGV("Creating BpBinder %p handle %d\n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle);//调用了IPCThreadState的成员函数self()
}
又调用了IPCThreadState的成员函数self(),实现如下:
~/Android/frameworks/base/libs/binder
----IPCThreadState.cpp
IPCThreadState* IPCThreadState::self()
{
if (gHaveTLS) {//第二次为true
restart:
const pthread_key_t k = gTLS;//利用第一次创建的gTLS
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);//获取IPCThreadState类,有pthread_getspecific(k),就一定有phread_setspecific;从线程本地存储空间获取对象
if (st) return st;
return new IPCThreadState;//构造函数中有phread_setspecific
}
if (gShutdown) return NULL;
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {//第一次执行这里,创建了gTLS
if (pthread_key_create(&gTLS, threadDestructor) != 0) {//创建线程本地存储空间
pthread_mutex_unlock(&gTLSMutex);
return NULL;
}
gHaveTLS = true;//为第二次做准备
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;//返回开头
}
第一次,gHaveTLS为false,所以进入下面的代码,创建了gTLS,而且gHaveTLS为true。第二次gHaveTLS为true,利用第一次创建的gTLS,获取IPCThreadState类,如果获取不到,就创建该类,在创建该类的过程中,调用了phread_setspecific函数,new IPCThreadState实现如下:
~/Android/frameworks/base/libs/binder
----IPCThreadState.cpp
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),//因为单例模式,就是刚才创建的ProcessState对象
mMyThreadId(androidGetTid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
pthread_setspecific(gTLS, this);//调用了这个函数,下次就是pthread_getspecific获取到了;将对象保存在线程本地存储空间
clearCaller();
mIn.setDataCapacity(256);//输入容量256
mOut.setDataCapacity(256);//输出容量256
}
由于是单例模式,所以mProcess保存的就是刚刚创建的ProcessState对象。下次调用IPCThreadState::self只要在同一个线程中,就返回刚刚创建的IPCThreadState对象,因为每个线程有独一无二的gTLS。
开始执行incWeakHandle,参考博客http://blog.csdn.net/jltxgcy/article/details/27638717,此时Server进程等到下次使用IO控制命令BINDER_WRITE_READ进入到Binder驱动程序时,再请求Binder驱动程序增加相应的Binder引用对象的强引用计数和弱引用计数。
4、调用模板函数interface_cast<IServiceManager>将前面获得的Binder代理对象封装成一个Service Manager代理对象,因为#include <binder/IServiceManager.h>。IServiceManager.h包含了#include <binder/IInterface.h>,所以可以调用。
~/Android/frameworks/base/include/binder
----IInterface.h
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
由于INTERFACE为IServiceManger,所以展开如下:
template<typename IServiceManager>
inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj);//静态方法所以直接调用
}
调用IServiceManager接口的成员函数asInterface,将一个句柄值为0的Binder代理对象封装为一个Service Manger代理对象。
IServiceManager接口的成员函数asInterface是通过宏IMPLEMENT_META_INTERFACE实现,如下所示:
~/Android/frameworks/base/libs/binder
----IServiceManager.cpp
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
展开后如下:
android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj)
{
android::sp<IServiceManager> intr;
if (obj != NULL) {
intr = static_cast<IServiceManager*>(
obj->queryLocalInterface(IServiceManager::descriptor).get());//返回NULL
if (intr == NULL) {
intr = new BpServiceManager(obj); //创建了Service Manager代理对象
}
}
return intr;
}
参数obj指向一个Binder代理对象,即一个BpBinder对象,它的成员函数queryLocalInterface的返回值为NULL。因此,最后会创建一个Service Manager代理对象,即一个BpServiceManger对象,并且将它的IServiceManager接口返回给调用者。
uml类图如下:
BpBinder代理对象被保存在BpRefBase类的成员变量mRemote中。
三、目前为止各对象的引用计数
BpServiceManager受弱指针控制,ProcessState受强指针控制,BpBinder受弱指针控制。
static void instantiate()
{
defaultServiceManager()->addService(String16(FREG_SERVICE), new FregService());
}
出了这个函数,sp<IServiceManager>的强引用计数为1,弱引用计数为1,指向了全局的变量。
sp<ProcessState>的强引用计数为1,弱引用计数为1,指向了全局的变量。
sp<IBinder>的强引用计数为1,弱引用计数为1,指向了刚刚new BpBinder(0),即FregServer进程的Binder代理对象。
因为如下代码:
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.
}
}