简单理解 Binder 机制
- 一、为什么要用 Binder
- 二、Binder 进程间通信机制
- 三、Java 层中的 Binder 分析
- 关键一:getIServiceManager()
- 关键 1.1:ServiceManagerNative.asInterface() 需要关键 1.2 的返回值作为参数,那么我们先看关键 1.2 吧
- 关键 1.2:BinderInternal.getContextObject()
- 关键 1.2.1:ProcessState::self()
- 关键 1.2.1.1:new ProcessState("/dev/binder")
- 关键 1.2.2:ProcessState::self()->getContextObject(NULL)
- 关键 1.2.2.1:getStrongProxyForHandle(0)
- 关键 1.2.3:javaObjectForIBinder()
- 回到 关键 1.1:ServiceManagerNative.asInterface()
- 关键 1.1.1:obj.queryLocalInterface()
- 关键二:getIServiceManager().addService() 注册服务
- 关键 2.1:Parcel#writeStrongBinder()
- 关键 2.1.1:nativeWriteStrongBinder()
- 关键 2.1.1.1:flatten_binder()
- 关键 2.1.1.1.1:finish_flatten_binder()
- 关键 2.2:BinderProxy#transact()
- 关键三:BpBinder::transact()
- 关键 3.1:IPCThreadState::self()
- 关键 3.2:IPCThreadState::self()->transact()
- 关键 3.2.1:writeTransactionData()
- 关键 3.2.2:waitForResponse()
- 关键四:talkWithDriver()
- 关键 4.1:ioctl()
- 处理 BR_TRANSACTION 返回协议的同时:
- 发送和处理 BC_REPLY 命令协议:
- 发送和处理 BR_REPLY 返回协议:
- 四、AIDL
一、为什么要用 Binder
Android 应用程序是由 Activity、Service、Broadcast Receiver 和 Content Provider 四种类型的组件构成的,四大组件运行可能在相同或不同进程中运行,Android 系统中系统组件运行在独立的进程中,系统服务运行在系统进程 System 中,不同进程的双方如何通信
Android 系统是基于 Linux 内核开发的。Linux 内核提供了丰富的进程间通信机制,如管道(pipe)、信号(Signal)、消息队列(Meessage)、共享内存(Share Memory)和插口(Socket)等。然而,Android 系统并没有采用这些传统的进程间通信机制,而是开发了一套新的进程间通信机制——Binder。与传统的进程间通信机制相比,Binder 进程间通信机制在进程间传输数据时,只需要执行一次复制操作,因此,它不仅提高了效率,而且节省了内存空间
二、Binder 进程间通信机制
Binder 进程间通信机制中涉及了 Client、Service、Server Manager 和 Binder 驱
动程序四个角色
Client、Service 和 Service Manager 运行在用户空间,而 Binder 驱动程序运行在内核空间,其中,Service Manager 和 Binder 驱动程序由系统负责提供,而 Client 和 Service 组件由应用程序来实现。Client、Service 和 Service Manager 均是通过系统调用 open、mmap 和 ioctl 来访问设备文件 /dev/binder,从而实现与 Binder 驱动程序的交互,而交互的目的就是为了能够间接地执行进程间通信
三、Java 层中的 Binder 分析
Java 层 Binder 系统是 Native 层 Binder 系统的一个镜像,但这个镜像终归还需借助 Native 层 Binder 系统来开展工作,平常使用的 Java 层 Binder 要想正常工作离不开 Native 层 Binder 的帮忙
下面我们看一下服务注册到 ServiceManager 的过程,即 addService() 的整个通信过程
1.向 ServiceManager 注册服务
向 ServiceManager 注册服务的函数叫 addService(),其代码如下:
[ServiceManager.java–>ServiceManager.addService()]
/**
* Place a new @a service called @a name into the service
* manager.
*
* @param name the name of the new service
* @param service the service object
*/
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service, false);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
/**
* Place a new @a service called @a name into the service
* manager.
*
* @param name the name of the new service
* @param service the service object
* @param allowIsolated set to true to allow isolated sandboxed processes
* to access this service
*/
public static void addService(String name, IBinder service, boolean allowIsolated) {
try {
// 关键一:getIServiceManager()
// 关键二:getIServiceManager().addService()
getIServiceManager().addService(name, service, allowIsolated);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
关键一:getIServiceManager()
问题一:getIServiceManager() 方法返回是什么,ServiceManager 的代理对象吗
[ServiceManager.java–>ServiceManager.getIServiceManager()]
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
// 调用 asInterface,传递的参数类型为 BinderInternal.getContextObject()
// 关键 1.1:ServiceManagerNative.asInterface()
// 关键 1.2:BinderInternal.getContextObject()
sServiceManager = ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
关键 1.1:ServiceManagerNative.asInterface() 需要关键 1.2 的返回值作为参数,那么我们先看关键 1.2 吧
关键 1.2:BinderInternal.getContextObject()
BinderInternal.getContextObject() 方法是一个 native 函数,参考其实现:
[android_util_Binder.cpp–>android_os_Bindernal_getContextObject()]
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
// 下面这句代码将返回一个 BpProxy 对象,其中 NULL(即 0,用于标识目的端)指定 Proxy 通信的目的端是 ServiceManager
// 关键 1.2.1:ProcessState::self()
// 关键 1.2.2:ProcessState::self()->getContextObject(NULL)
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
// 关键 1.2.3:javaObjectForIBinder()
return javaObjectForIBinder(env, b);
}
关键 1.2.1:ProcessState::self()
ProcessState::self() 方法用于获取 ProcessState 实例对象
[frameworks/native/libs/binder/ProcessState.cpp]
// 单例模式,保证每个进程只打开一次 Binder 驱动
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
// 关键 1.2.1.1:实例化 ProcessState
gProcess = new ProcessState("/dev/binder");
return gProcess;
}
关键 1.2.1.1:new ProcessState("/dev/binder")
实例化 ProcessState
[frameworks/native/libs/binder/ProcessState.cpp]
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,给 Binder 分配一块虚拟地址空间
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.");
}
关键 1.2.2:ProcessState::self()->getContextObject(NULL)
[frameworks/native/libs/binder/ProcessState.cpp]
// 参数传入 NULL
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
// 关键 1.2.2.1:getStrongProxyForHandle(0)
return getStrongProxyForHandle(0);
}
关键 1.2.2.1:getStrongProxyForHandle(0)
[frameworks/native/libs/binder/ProcessState.cpp]
// handle:参数传入 0
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
// 如果当前没有新的 BpBinder,或无法获取当前 BpBinder 的弱引用,需要创建一个新的 BpBinder
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
b = new BpBinder(handle); // b 为 Native 层 BpBinder 对象,handle 为 0
e->binder = b; // 给 e->binder 赋值,下次直接返回已有的 BpBinder 对象
// 设置 BpBinder 弱引用
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
// 看这里,最终返回了 result,其类型为 BpBinder,且其 handle 为 0
return result;
}
到此,我们知道 关键 1.2:BinderInternal.getContextObject() 返回的是 BpBinder,且其 handle 为 0
关键 1.2.3:javaObjectForIBinder()
[android_util_Binder.cpp–>javaObjectForIBinder()]
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
if (val == NULL) return NULL;
if (val->checkSubclass(&gBinderOffsets)) {
jobject object = static_cast<JavaBBinder*>(val.get())->object();
return object;
}
...
// val 对象实际类型是 Native 层 BpBinder
// Native 层的 BpBinder 中有一个 ObjectManager 成员变量,它用来管理 Native BpBinder 上创建的 Java BpBinder 对象
// 下面这个 findObject() 函数用来判断 gBinderProxyOffsets 是否已经保存在 ObjectManager 中。如果是,那就需要删除这个旧的对象
// gBinderProxyOffsets 对应 Java 层的 BinderProxy
// 也就是说,通过 findObject() 函数,看看 Native 层的 BpBinder 对象的成员变量 ObjectManager 有没有保存 Java 层的 BinderProxy 对象,有就删除,重新创建一个新的 Java 层的 BinderProxy 对象,然后保存到 Native 层的 BpBinder 对象的成员变量 ObjectManager 中
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) {
jobject res = jniGetReferent(env, object);
if (res != NULL) {
return res;
}
// 减去该 Proxy 对象的引用计数
android_atomic_dec(&gNumProxyRefs);
// 删除该 Proxy 对象
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
// 创建一个新的 BinderProxy 对象(Java 层)
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
// val.get():获取智能指针指向的对象,直接看成 env 就行
// 把 Native 层的 BpProxy 的指针指向的对象 val.get() 保存到 BinderProxy 的成员字段 mObject 中
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
// 将这个新创建的(Java 层) BinderProxy 对象注册(attach)到(Native 层) BpBinder 的 ObjectManager 中
// 同时注册一个回调 proxy_cleanup。当 BinderProxy 对象撤销(detach)的时候,该函数会被调用,以释放一些资源,读者可自行研究 proxy_clean 函数
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
// DeathRecipientList 保存了一个用于死亡通知的 list
sp<DeathRecipientList> drl = new DeathRecipientList;
drl->incStrong((void*)javaObjectForIBinder);
// 将死亡通知 list 和 BiderProxy 对象联系起来
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
// Note that a new object reference has been created.
// 增加该 Proxy 对象的引用计数
android_atomic_inc(&gNumProxyRefs);
// 下面这个函数用于垃圾回收。创建的 Proxy 对象一旦超过 200 个,该函数将调用 BinderInter 类的 ForceGc 做一次垃圾回收
incRefsCreated(env);
}
// 返回 BinderProxy 对象(Java 层)
return object;
}
到此,通过 javaObjectForIBinder() 方法,我们知道方法最终返回了一个 Java 层的 BinderProxy 对象,并且 BinderProxy 对象的 mObject 保存了 Native 层的 BpProxy 对象
- 创建了一个 Java 层的 BinderProxy 对象
- 通过 JNI,该 BinderProxy 对象和一个 Native 的 BpProxy 对象挂钩,而该 BpProxy 对象的通信目标就是 ServiceManager
回到 关键 1.1:ServiceManagerNative.asInterface()
把关键 1.2 的返回值作为参数,那么就相当于是 ServiceManagerNative.asInterface(BinderProxy)
[frameworks/base/core/java/android/os/ServiceManagerNative.java]
// 该成员变量在父类 IServiceManager 中定义
static final String descriptor = "android.os.IServiceManager";
/**
* Cast a Binder object into a service manager interface, generating
* a proxy if needed.
*/
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
// 关键 1.1.1:obj.queryLocalInterface()
IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
// 调用了 ServiceManagerProxy 的构造方法,参数类型为 BinderProxy
return new ServiceManagerProxy(obj);
}
关键 1.1.1:obj.queryLocalInterface()
obj 实际为 BinderProxy,类 BinderProxy 定义在 Binder.java 中
[frameworks/base/core/java/android/os/Binder.java]
public IInterface queryLocalInterface(String descriptor) {
// 返回 null
return null;
}
对于 关键 1.1 ServiceManagerNative.asInterface() 方法:
- 返回的是 ServiceManagerProxy 对象(回答 问题一,即 getIServiceManager() 返回的对象确实是 ServiceManager 的代理对象)
- ServiceManagerProxy 对象包含了 BinderProxy
- BinderProxy 关联着 Native 的 BpProxy 对象
- Native 的 BpProxy 对象的通信目标就是 ServiceManager
关键二:getIServiceManager().addService() 注册服务
getIServiceManager() 返回的是 ServiceManagerProxy 对象(ServiceManager 的代理对象)
[ServiceManagerNative.java–>ServiceManagerProxy.addService()]
class ServiceManagerProxy implements IServiceManager {
// 在 关键 1.1 中调用了 ServiceManagerProxy 的构造方法,参数类型为 BinderProxy
// 因此这里 remote 实际类型为 BinderProxy
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
public IBinder asBinder() {
return mRemote;
}
public IBinder getService(String name) throws RemoteException {...}
public IBinder checkService(String name) throws RemoteException {...}
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name); // 要注册的 Service 的名称
// 关键 2.1:Parcel#writeStrongBinder()
data.writeStrongBinder(service); // 将 Service 写进 Parcel
data.writeInt(allowIsolated ? 1 : 0);
// mRemote 实际上就是 BinderProxy 对象,调用它的 transact() 方法,将封装好的请求数据发送出去
// 关键 2.2:BinderProxy#transact()
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
public String[] listServices() throws RemoteException {...}
public void setPermissionController(IPermissionController controller) throws RemoteException {...}
private IBinder mRemote;
}
关键 2.1:Parcel#writeStrongBinder()
[frameworks/native/libs/binder/Parcel.cpp]
/**
* Write an object into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
public final void writeStrongBinder(IBinder val) {
// 关键 2.1.1:nativeWriteStrongBinder()
nativeWriteStrongBinder(mNativePtr, val);
}
关键 2.1.1:nativeWriteStrongBinder()
nativeWriteStrongBinder() 是一个 native 函数
[frameworks/native/libs/binder/Parcel.cpp]
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
// 关键 2.1.1.1:flatten_binder()
return flatten_binder(ProcessState::self(), val, this);
}
关键 2.1.1.1:flatten_binder()
将 binder 对象转为 struct flat_binder_object 对象
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
// 定义 flat_binder_object 结构体
flat_binder_object obj;
// 当结构体 flat_binder_object 描述的是一个 Binder 实体对象(还可以描述 Binder 引用对象)时,才有实际意义
// 可用来描述 Binder 实体对象在处理一个进程间通信请求时,其所运行的线程应当具有的最小线程优先级
if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
/* minimum priority for all nodes is nice 0 */
obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
} else {
/* minimum priority for all nodes is MAX_NICE(19) */
obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
}
if (binder != NULL) { // 传入的 binder 肯定不为 NULL,走这里
// 其实 binder 是我们要注册的服务,即 BBinder
// 可以查看 frameworks/native/libs/binder/Binder.cpp 中的 BBinder::localBinder() 函数,返回的是 this 即 BBinder 本身
// 也很容易理解,服务获取本地 Binder,返回的是自己没毛病
IBinder *local = binder->localBinder(); // local 返回 this,不为空
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == NULL) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
obj.type = BINDER_TYPE_HANDLE;
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;
obj.cookie = 0;
} else { // local 不为空,走这里
// 下面是给 lat_binder_object 结构体成员变量赋值的过程
// type 可用来区分当前结构体描述的是 Binder 实体类型还是 Binder 引用类型
obj.type = BINDER_TYPE_BINDER; // type = BINDER_TYPE_BINDER,表示描述的是一个强类型的 Binder 实体对象
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs()); // 当前是描述的是 Binder 实体对象,binder 指向与该 Binder 实体对象对应的一个 Service 组件内部的一个弱引用计数对象(weakref_impl)的地址
obj.cookie = reinterpret_cast<uintptr_t>(local); // 当前是描述的是 Binder 实体对象,cookie 指向 Service 组件的地址
}
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
// 关键 2.1.1.1.1:finish_flatten_binder()
return finish_flatten_binder(binder, obj, out);
}
- 对于 Binder 实体,使用 cookie 记录 Binder 实体的指针
- 对于 Binder 代理,使用 handle 记录 Binder 代理的句柄
关键 2.1.1.1.1:finish_flatten_binder()
将 struct flat_binder_object 对象写入到 Parcel out 中
[frameworks/native/libs/binder/Parcel.cpp]
inline static status_t finish_flatten_binder(
const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
{
// Parcel::writeObject() 函数作用:
// 添加前,计算容量还够
// 1. 通过指针 mData 和指针偏移量 mDataPos 来存储数据 flat
// 2. 调用 finishWrite(sizeof(flat_binder_object)) 函数更新指针偏移量 mDataPos
// 添加前,计算容量不够
// 调用 growData() 函数更新指针 mData
// 使用 goto restart_write 语句,代码返回到再次添加数据的地方执行
return out->writeObject(flat, false);
}
小结:关键 2.1 把 binder 对象转为 struct flat_binder_object 对象,写到了 Parcel out 中
关键 2.2:BinderProxy#transact()
BinderProxy 的 transact 是一个 native 函数
[android_util_Binder.cpp–>android_os_BinderProxy_transact()]
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
...
// 从 Java 的 Parcel 对象中得到作为参数的 Native 的 Parcel 对象
Parcel* data = parcelForJavaObject(env, dataObj);
if (data == NULL) {
return JNI_FALSE;
}
// 得到一个用于接收回复的 Parcel 对象
Parcel* reply = parcelForJavaObject(env, replyObj);
if (reply == NULL && replyObj != NULL) {
return JNI_FALSE;
}
// 还记得在 关键 1.2.3:javaObjectForIBinder() 函数中的一些对应关系,这里再总结一下:
// gBinderProxyOffsets 对应 Java 层的 BinderProxy
// Native 层的 BpProxy 保存在 Java 层 BinderProxy 对象的成员变量 mObject 中
// 因此,我们可以通过 gBinderProxyOffsets 获取到 Java 层的 BinderProxy,通过 Java 层的 BinderProxy 的成员变量 mObject 获取到 Native 层的 BpProxy
// 获取 Native 的 BpBinder 对象
IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);
if (target == NULL) {
return JNI_FALSE;
}
...
// 通过 Native 的 BpBinder 对象将请求发送给 ServiceManager
// code:ADD_SERVICE_TRANSACTION
// flags:0
// 关键三:BpBinder::transact()
status_t err = target->transact(code, *data, reply, flags);
...
signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
return JNI_FALSE;
}
上面的代码流程只是 Java 层注册服务到 Service Manager 过程的一部分,即把注册服务的请求交给了 Native 层的 BpBinder,由此,我们发现 Java 层的 Binder 最终还是要借助 Native 的 Binder 进行通信
http://www.cnblogs.com/zhangxinyan/p/3487905.html
关键三:BpBinder::transact()
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) {
// mHandle:查看 关键 1.2.2.1:getStrongProxyForHandle(0) 函数,其中 handle 传入的是 0
// code:ADD_SERVICE_TRANSACTION
// data:要传递给 Binder 驱动的数据
// reply:用于接收回复的 Parcel 对象
// flags:传入的 0
// BpBinder::transact() 最终把 transact 的活交给了 IPCThreadState
// 关键 3.1:IPCThreadState::self()
// 关键 3.2:IPCThreadState::self()->transact()
status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
关键 3.1:IPCThreadState::self()
[frameworks/native/libs/binder/IPCThreadState.cpp]
static bool gHaveTLS = false; // gHaveTLS 默认为 false
static pthread_key_t gTLS = 0;
IPCThreadState* IPCThreadState::self()
{
// 首次进入 gHaveTLS 默认为 false
if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
// 创建 IPCThreadState 对象实例并返回
return new IPCThreadState;
}
if (gShutdown) {
return NULL;
}
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) { // 首次进入 gHaveTLS 默认为 false,走这里
// pthread_key_create():创建线程的 TLS(Thread Local Storage)
// - 用于创建线程本地存储空间
// - 每个线程都有自己的 TSL(Thread Local Storage),该空间为线程私有,线程间不共享
// - 可通过 pthread_setspecific()、pthread_getspecific() 函数在线程中存取数据
int key_create_value = pthread_key_create(&gTLS, threadDestructor);
if (key_create_value != 0) {
pthread_mutex_unlock(&gTLSMutex);
return NULL;
}
// gHaveTLS 置为 true
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
// 首次进入 gHaveTLS 默认为 false,执行 goto restart 语句,代码从第 7 行开始执行,创建 IPCThreadState 对象
goto restart;
}
IPCThreadState::self() 函数最终会创建并返回 IPCThreadState 对象
关键 3.2:IPCThreadState::self()->transact()
[frameworks/native/libs/binder/IPCThreadState.cpp]
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
// 数据错误检查
status_t err = data.errorCheck();
// flags 传入 0,此时置为 TF_ACCEPT_FDS
flags |= TF_ACCEPT_FDS;
...
if (err == NO_ERROR) { // 数据没错
...
// 关键四:writeTransactionData() 用来传输数据
// flags:TF_ACCEPT_FDS
// handle:传入的 0
// code:ADD_SERVICE_TRANSACTION
// data:要传递给 Binder 驱动的数据
// 关键 3.2.1:writeTransactionData()
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) { // flags:传入的 0,走这里
...
// reply:用于接收回复的 Parcel 对象
if (reply) { // 不为空,走这里
// 关键 3.2.2:waitForResponse()
err = waitForResponse(reply); // 发送 BC_TRANSACTION 命令协议
} else { // 当前需要同步,但是 reply 又为 false,表示不需要等待结果返回
Parcel fakeReply; // fake 中文意思为伪造,这里是伪造 reply
err = waitForResponse(&fakeReply);
}
...
} else { // ONE_WAY,不需等待 reply
err = waitForResponse(NULL, NULL);
}
return err;
}
关键 3.2.1:writeTransactionData()
[frameworks/native/libs/binder/IPCThreadState.cpp]
// cmd:BC_TRANSACTION
// binderFlags:TF_ACCEPT_FDS
// handle:0
// code:ADD_SERVICE_TRANSACTION
// data:要传递给 Binder 驱动的数据
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
// binder 驱动通信的数据结构
binder_transaction_data tr;
tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
tr.target.handle = handle; // handle = 0,用于标识目的端
tr.code = code; // code = ADD_SERVICE_TRANSACTION
tr.flags = binderFlags; // binderFlags = TF_ACCEPT_FDS
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
// 数据错误检查
const status_t err = data.errorCheck();
if (err == NO_ERROR) { // 数据没有出错,给 binder_transaction_data 赋值
tr.data_size = data.ipcDataSize(); // 数据大小
tr.data.ptr.buffer = data.ipcData(); // 把 struct flat_binder_object 数据赋值给 tr.data.ptr.buffer
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t); // mObjectsSize,结构体在数组中的偏移量(size_t),会有很多个结构体???
tr.data.ptr.offsets = data.ipcObjects(); // mObjects,Binder 数据在结构体中的偏移量(uintptr_t),结构体中不止包含 Binder 数据,还有其他数据,要获取 Binder 数据,需要知道 Binder 数据在结构体中的偏移量???
} 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 在 IPCThreadState.h 中定义,类型为 Parcel,mOut 存储发往 Binder 设备的数据
// 先网 mOut 中写入请求码
mOut.writeInt32(cmd); // cmd = BC_TRANSACTION
// 再往 mOut 中写入请求数据
mOut.write(&tr, sizeof(tr)); // 将 binder_transaction_data 写入到 mOut 中
// 此时 Parcel mOut 的存储结构为:(cmd = BC_TRANSACTION)+(struct binder_transaction_data)
return NO_ERROR;
}
把 struct flat_binder_object 对象(在 Parcel 中传递的数据结构)转为 truct binder_transaction_data 对象(和 Binder 驱动通信的数据结构)
最后 Parcel mOut 的存储结构为:(cmd = BC_TRANSACTION)+(struct binder_transaction_data)
对于 struct binder_transaction_data,我们看看它的数据结构
struct binder_transaction_data {
union {
size_t handle; // 0
void *ptr;
} target;
void cookie;
unsigned int code; // ADD_SERVICE_TRANSACTION
unsigned int flags; // TF_ACCEPT_FDS
pid_t sender_pid;
uid_t sender_euid;
size_t data_size; // 存储数据的大小
size_t offsets_size; // 结构体数据偏移量
union {
struct {
const void *buffer; // 存储数据包括一般数据和 Binder 数据,当前这里对应 struct flat_binder_object 的数据
const void *offsets; // Binder 数据在当前 struct binder_transaction_data 数据结构中的偏移量
} ptr;
uint8_t buf[8];
} data;
};
target.handle:标识通信的目的端,为 0,即 ServiceManager
code :ADD_SERVICE_TRANSACTION,在后面用来区分到底是要调用那个函数
data_size:数据大小
data.ptr.buffer:存储的数据,有一般数据和 Binder 数据
offsets_size:数组内偏移量
data.ptr.offsets Binder 数据在整个数据中的偏移位置,加上上面数组内偏移量,就可以获取到 Binder 对象
关键 3.2.2:waitForResponse()
[frameworks/native/libs/binder/IPCThreadState.cpp]
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
// 关键四:talkWithDriver() 和 Binder 驱动程序进行交互
if ((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
...
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:
{
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));
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;
}
}
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
}
return err;
}
关键四:talkWithDriver()
和 Binder 驱动程序进行交互
[frameworks/native/libs/binder/IPCThreadState.cpp]
// talkWithDriver() 函数在 IPCThreadState.h 中声明,doReceive:为默认参数,默认值为 true
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
...
// binder_write_read 是用来与 binder 设备进行交换数据的结构
binder_write_read bwr;
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
// 请求命令的填充
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();
if (doReceive && needRead) {
// bwr 接收数据缓冲区信息的填充。如果以后收到数据,就直接填充在 mIn 中了(然后再交给 bwr???)
bwr.read_size = mIn.dataCapacity(); // mIn,接收来自 Binder 设备的数据
bwr.read_buffer = (uintptr_t)mIn.data(); // 把指针传给了 bwr
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
...
// 读缓存和写缓存都为空,则返回
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 defined(__ANDROID__)
// 通过 ioctl 不停的读写,跟 binder driver 进行通信
// 进入内核, 传递的参数是 struct binder_write_read
// 关键 4.1: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;
}
...
} while (err == -EINTR);
...
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())
mOut.remove(0, bwr.write_consumed); // 将已处理的命令移除
else
mOut.setDataSize(0);
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed); // 将读取出来的返回协议保存在 mIn 中,在返回到 waitForResponse 时,就可以解析 mIn 中的内容了
mIn.setDataPosition(0);
}
...
return NO_ERROR;
}
return err;
}
关键 4.1:ioctl()
进入内核,通过 ioctl 不停的读写,跟 binder driver 进行通信,传递的参数是 struct binder_write_read
内核处理过程:
- 读取 BC_TRANSACTION 命令协议和 struct binder_transaction _data
- 根据 handle 找到 Binder 实体对象,然后找到 Server Process
- 将一个 BR_TRANSACTION_COMPLETE 返回协议发送到 Client Process 中,把返回协议写到 mIn 中
- 现在已经返回到 IPCThreadState 的 talkWithDriver(),又返回到 waitForResponse() 中处理 BR_TRANSACTION_COMPLETE,然后开始等待 Server Process 返回结果
处理 BR_TRANSACTION 返回协议的同时:
- 将一个 BINDER_WORK_TRANSACTION_COMPLETE 工作项添加到 Client Process 队列中处理,同时将一个 BINDER_WORK_TRANSACTION 工作项添加到 Server Process 队列中处理
- 内核处理 BINDER_WORK_TRANSACTION_COMPLETE 工作项,向 Server Process发送了一个 BR_TRANSACTION返回协议
- ServiceManager 所在进程被唤醒后,会调用 binder_parse() 处理返回协议
- ServiceManager 根据参数,判断执行操作 SVC_MGR_ADD_SERVICE。调用对应的函數 do_add_service() 函数为要注册的 Service 创建 svcinfo 结构体,并添加到全局队列 svclist 中(以后就可以直接从全局队列 svclist 中查所需的 service 了)
发送和处理 BC_REPLY 命令协议:
ServiceManager 进程注册成功后,就会通过 IO 控制命令 BINDER_WRITE_READ 将 BC_REPLY 发送到 kernel
int binder_write(struct binder_state *bs, void *data, size_t len)
{
struct binder_write_read bwr;
int res;
bwr.write_size = len;
bwr.write_consumed = 0;
bwr.write_buffer = (uintptr_t) data;
bwr.read_size = 0;
bwr.read_consumed = 0;
bwr.read_buffer = 0;
// ioctl 过程
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < 0) {
fprintf(stderr,"binder_write: ioctl failed (%s)\n",
strerror(errno));
}
return res;
}
之后都是在 Kernel 中完成的操作,在 kernel 中的处理:
- 读取 BC_REPLY命令协议
- 找到 target process(现在是Client Process)
- 将一个 BINDER_WORK_TRANSACTION_COMPLETE 工作项添加到 ServiceManager Process 队列中处理,同时将一个 BINDER_WORK_TRANSACTION 工作项添加到 Client Process 队列中处理,这两个工作项是并行处理的
- 处理 BINDER_WORK_TRANSACTION_COMPLETE 工作项,将一个 BR_TRANSACTION_COMPLETE 返回协议发送到 ServiceManager 中
ServiceManager 处理完 BR_TRANSACTION_COMPLETE 后,就又开始等待新的进程间通信请求了
发送和处理 BR_REPLY 返回协议:
在前面处理 BC_REPLY 中,会并行将一个 BINDER_WORK_TRANSACTION 工作项添加到 Client Process 队列中处理
- kernel 根据 BINDER_WORK_TRANSACTION 工作项,向 Client Process 发送一个 BR_REPLY 返回协议
- Client Process 返回到 IPCThreadState的talkWithDriver(),再回到 waitForResponse 中处理 BR_REPLY
- waitForResponse() 函数中将返回的結果取出,保存在 Parcel 对象的 reply 中。然后跳出循环,方法结束。至此,Service 的注册过程就执行完了
Service 注册之后,就会启动 Binder thread pool,等待 client 的请求,此时 Service 将作为 Service 端处理收到的请求,收到的请求会通过 executeCommand() 进行处理
请求和响应
处理 BR_TRANSACTION 返回协议的过程,对应我们平时请求服务,挂起客户端进程的阶段
处理 BR_REPLY 返回协议的过程,对应我们平时请求服务,收到服务端返回的结果的阶段
四、AIDL
在 三、Java 层中的 Binder 分析 中,我们发现在 Java 层 Binder 的架构中,Bp 端(客户端)可以通过 BinderProxy(如:Java 层 ServerManagerProxy#addService() -> Java 层 BinderProxy#transact() -> 获取 Java 层 BinderProxy 对象 mObject 中保存的 native 层 BpBinder,BpBinder#transact())的 transact() 方法与 Bn 端(服务端)发送请求,而 Bn 端通过继承 Binder 类重写 onTransact() 接受并处理来自 Bp 端的请求。这个结构非常清晰而且简单,但是实现起来却颇为繁琐。于是 Android 提供了 AIDL 语言以及 AIDL 解释器自动生成一个服务端的 Bn 端 以及客户端的 Bp 端
这里先介绍使用 AIDL 来进行进程间通信的流程,分为服务端和客户端两个方面。
- 服务端
服务端首先要创建一个 Service 用来监听客户端的连接请求,然后创建一个 AIDL 文件,将暴露给客户端的接口在这个 AIDL 文件中声明,最后在 Service 中实现这个 AIDL 接口即可 - 客户端
客户端所要做事情就稍微简单一些,首先需要绑定服务端的 Service,绑定成功后,将服务端返回的 Binder 对象转成 AIDL 接口所属的类型,接着就可以调用 AIDL 中的方法了 - AIDL 接口的创建
首先看 AIDL 接口的创建,如下所示,我们创建了一个后缀为 AIDL 的文件,在里面声明了一个借口和两个接口方法
// IBookManager.aidl
package com.ryg.chapter_2.aidl;
import com.ryg.chapter_2.aidl.Book;
interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);
}
另外一个需要注意的地方是,如果 AIDL 文件中用到了自定义的 Parcelable 对象,那么必须新建一个和它同名的 AIDL 文件,并在其中声明它为 Parcelable 类型。在上面的 IBookManager.aidl 中,我们用到了 Book 这个类,所以,我们必须要创建 Book.aidl,然后在里面添加如下内容:
package com.ryg.chapter_2.aidl;
parcelable Book;
- 远程服务端 Service 的实现
上面讲述了如何定义 AIDL 接口,接下来我们就需要实现这个接口了。我们先创建一个 Service,称为 BookManagerService,代码如下:
public class BookManagerService extends Service {
private static final String TAG = "BMS";
private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<Book>();
private Binder mBinder = new IBookManager.Stub() {
@Override
public List<Book> getBookList() throws RemoteException {
return mBookList;
}
@Override
public void addBook(Book book) throws RemoteException {
mBookList.add(book);
}
};
@Override
public void onCreate() {
super.onCreate();
mBookList.add(new Book(1, "Android"));
mBookList.add(new Book(2, "Ios"));
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
- 客户端的实现
客户端的实现就比较简单了,首先要绑定远程服务,绑定成功后将服务端返回的 Binder 对象转换成 AIDL 接口,然后就可以通过这个接口去调用服务端的远程方法了,代码如下所示
public class BookManagerActivity extends Activity {
private static final String TAG = "BookManagerActivity ";
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// 问题 1:这里的 service 其实是 BookManagerService#onBind() 方法的返回值,即服务端的 Sub 对象的本地代理
// 至于为什么是 BookManagerService#onBind() 方法的返回值,请参考:[bindService() 调用流程](https://blog.csdn.net/qq_21586317/article/details/88771731)
// 问题 2:为什么要 IBookManager.Stub.asInterface() 这样调用
// 用于将服务端的 Binder 对象转换成客户端所需的 AIDL 接口类型的对象,这种转换过程是区分进程的,如果客户端和服务端位于同一进程,那么此方法返回的就是服务端的 Sub 对象本身,否则返回的是系统封装后的 Stub.proxy 对象,而 Stub.proxy 对象实现了 IBookManager 接口,因此在下面可以顺利通过接口方法进行远程调用
IBookManager bookManager = IBookManager.Stub.asInterface(service);
try {
List<Book> list = bookManager.getBookList();
Log.i(TAG, "query book list, list type:" + list.getClass().getCanonicalName());
Log.i(TAG, "query book list:" + list.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onServicceDisconnected(ComponentName className) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_book_manager);
Intent intent = new Intent(this, BookManagerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
unbindService(mConnection);
super.onDestroy();
}
}