mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// sigh
ALOGE(“Using %s failed: unable to mmap transaction memory.\n”, mDriverName.c_str());
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, “Binder driver could not be opened. Terminating.”);
}
注释1处,ProcessState
的构造方法首先调用了open_driver()
方法,这个方法一看名字就知道,是打开驱动嘛,它的参数不就是我们刚才看到的传进去的/dev/binder
,也就是说ProcessState
在构造方法处打开了Binder
驱动。看看它是怎么打开驱动的吧
open_driver
//frameworks/native/libs/binder/ProcessState.cpp
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);//1
if (fd >= 0) {
…
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);//2
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;
}
注释1处用于打开/dev/binder设备并返回文件操作符fd,这样就可以操作内核的Binder驱动了。
Linux 系统中,把一切都看做是文件,当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符,文件描述符就是内核为了高效管理已被打开的文件所创建的索引,用来指向被打开的文件,所有执行I/O操作的系统调用都会通过文件描述符。
注释2处的ioctl函数的作用就是和Binder设备进行参数的传递,这里的ioctl函数用于设定binder支持的最大线程数为15(maxThreads的值为15)。
在用户空间,使用ioctl方法系统调用来控制设备。这是方法原型:
/*
fd:文件描述符
cmd:控制命令
…:可选参数:插入argp,具体内容依赖于cmd/
int ioctl(int fd,unsigned long cmd,…);
用户程序所作的只是通过命令码告诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要做的事情。所以在用户空间我们想做什么事情都是通过这个方法以命令的形式告诉Binder驱动,Binder驱动收到命令执行相应的操作。
mmap
在刚才的注释2处就是大名鼎鼎的内存映射。内存映射函数mmap,给binder分配一块虚拟地址空间。它会在内核虚拟地址空间中申请一块与用户虚拟内存相同大小的内存,然后再申请物理内存,将
同一块物理内存分别映射到内核虚拟地址空间和用户虚拟内存空间,实现了内核虚拟地址空间和用户虚拟内存空间的数据同步操作。
这是函数原型:
//原型
/*
addr: 代表映射到进程地址空间的起始地址,当值等于0则由内核选择合适地址,此处为0;
size: 代表需要映射的内存地址空间的大小,此处为1M-8K;
prot: 代表内存映射区的读写等属性值,此处为PROT_READ(可读取);
flags: 标志位,此处为MAP_PRIVATE(私有映射,多进程间不共享内容的改变)和 MAP_NORESERVE(不保留交换空间)
fd: 代表mmap所关联的文件描述符,此处为mDriverFD;
offset:偏移量,此处为0。
此处 mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
/
void mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset)
总的来说,ProcessState
做了两件事情,一是打开Binder驱动并返回文件操作符fd,二是通过mmap为Binder分配了一块虚拟内存空间,以达到内存映射的目的。
得到ProcessState
对象后,调用它的getContextObject
方法得到BpBinder
对象。
ProcessState.getContextObject
//frameworks/native/libs/binder/ProcessState.cpp
sp ProcessState::getContextObject(const sp& /caller/)
{
return getStrongProxyForHandle(0); //
}
在之前的篇幅中讲了,当请求服务的进程的handler是0的时候就是获取ServiceManager的BpBinder对象。这里的话就是获取获取handle=0
的IBinder。
ProcessState.getStrongProxyForHandle
//frameworks/native/libs/binder/ProcessState.cpp
sp ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp result;
AutoMutex _l(mLock);
//查找handle对应的资源项
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
Parcel data;
//通过ping操作测试binder是否准备就绪
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
//当handle值所对应的IBinder不存在或弱引用无效时,则创建BpBinder对象
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
首先查找handler所对应的资源,当handle值所对应的IBinder不存在或弱引用无效时会创建BpBinder
,否则直接获取。handle==0的特殊情况,即获取的是ServiceManager
,需要通过PING_TRANSACTION
来判断是否准备就绪。
创建BpBinder
//frameworks/native/libs/binder/BpBinder.cpp
BpBinder::BpBinder(int32_t handle)
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK); //延长对象的生命时间
IPCThreadState::self()->incWeakHandle(handle); //handle所对应的bindle弱引用 + 1
}
创建BpBinder
对象中会将handle相对应Binder的弱引用增加1.
创建完成以后我们就重新回到了getContextObject()
方法中
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
可以看到,使用了javaObjectForIBinder
方法将本地IBinder指针转为javaobject。然后返回给了Java层。
javaObjectForIBinder
//frameworks/base/core/jni/android_util_Binder.cpp
jobject javaObjectForIBinder(JNIEnv* env, const sp& val) {
if (val == NULL) return NULL;
if (val->checkSubclass(&gBinderOffsets)) { //返回false
jobject object = static_cast<JavaBBinder*>(val.get())->object();
return object;
}
AutoMutex _l(mProxyLock);
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) { //第一次object为null
jobject res = jniGetReferent(env, object);
if (res != NULL) {
return res;
}
android_atomic_dec(&gNumProxyRefs);
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
//创建BinderProxy对象
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
//BinderProxy.mObject成员变量记录BpBinder对象
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
//将BinderProxy对象信息附加到BpBinder的成员变量mObjects中
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
sp drl = new DeathRecipientList;
lf));
//将BinderProxy对象信息附加到BpBinder的成员变量mObjects中
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
sp drl = new DeathRecipientList;