Binder解析
一. 概述
Binder作为Android中最主要的进程间通讯方式,它涉及到的主要有以下这几个方面
- Client端
- Service端
- ServiceManager
- Binder驱动
Binder通信采用了C/S架构,它和TCP/IP网络通讯有很多相似的地方。
TCP/IP网络通讯最典型的一个过程(例如访问百度首页:)如下;
Client端要访问一个域名,需要先访问DNS服务器查询域名对应的ip地址。
当然,如果Client端已经知道http地址对应的ip地址,可以跳过这一步。比如Windows系统中就内置了一个hosts文件,可以直接查询到常用网址对应的ip地址。
DNS服务端返回域名对应的ip地址。
Client连接这个ip地址,与Service端进行通讯。
其中,在这中间充当桥梁的硬件是路由器,它负责将根据ip地址选择合适的路径,将数据投递到正确的目标位置。
Binder通讯中,Binder驱动就相当于是这个路由器,ServiceManger就是DNS服务商。
二. 智能指针
智能指针在Binder中比比皆是,所以我们先来回顾下智能指针的知识。
指针
Android应用开发使用的语言主要是Java,Java和C/C++有一个很大的不同,就是Java没有指针的概念,它被Java隐藏在了底层。 C/C++中指针是非常重要的一个概念。是一把非常锋利的武器,然而这把武器用不好,就会伤到我们自己。 C/C++中指针常见的问题有这些
指针没有初始化
new对象,但用完了没有delete对象,造成内存泄漏。
野指针:我们new了一个对象A,用完也delete了这个对象A。然而,我们没有把指向A对象的指针ptr置为null,导致B对象使用这个指针时发现指针还有指向,会认为A对象依然存活着,这就会出现严重的后果。
或者ptr1和ptr2都指向对象A,我们用完对象,调用了delete删除A,也将ptr1置为null了,然而ptr2并不知道它指向的对象已经死亡了。这也会造成野指针。
从而 就出现了只能指针的需求,来解决上面的三个缺陷。
智能指针
第一个缺陷很好解决,智能指针只需要在创建时自动置为null即可。
第二点。需要在对象不被需要的时候自动的delete。
智能指针作为一个类,内部有个属性用来指向Object。
Object有一个父类RefBase,所有Object都要继承它。
RefBase包含有一个引用计数器,记录指向它的智能指针个数。并提供两个方法incCount,decCount。
每调用一次incCount,计数器+1.
每调用一次decCount,计数器-1,并且判断,当计数器为0时,delete掉Object。
每次需要智能指针指向一个Object时,内部属性指向Object的引用地址,并且调用Object的incCount。
每当智能智能不再指向一个Object时,调用Object的decCount,并且内部属性置为null。
然而这又会出现一个问题,加入当一个父对象parent指向一个子对象child,子对象又指向父对象时,这就会出现循环引用,出现问题。从而出现类强弱指针的设计思路:
- 智能指针分为强指针sp和弱指针wp。
- Object继承自RefBase,它提供了一个weakref_iml类型的引用计数器,可以同时进行强弱引用的控制,内部分别用mStrong与mWeak来计数。
- 当incStrong增加强引用计数时,也会同时增加弱引用。
- 当incWeak增加弱引用计数时,只会增加弱引用计数。
- 使用者通过设置不同的引用计数器规则来设置不同的删除对象时机。
Binder驱动
Binder驱动是一个标准的Linux驱动,它将自己注册成一个misc device,并向上层提供一个/dev/binder节点。 Binder节点并不对应真实的硬件设备。Binder驱动运行于内核态,可提供
open(),ioctl(),mmap()等常用的文件操作。Linux中字符设备的注册需要
alloc_chrdev_region(),cedv-init()等许多操作才能在内核中注册自己。而misc类型驱动注册相对简单,调用misc_register()即可。binder为上层应用提供了6个接口:
binder_pollbinder_ioctl,binder_mmap,binder_open,binder_flush,binder_release上层进程需要使用Binder驱动时,首先需要打开/dev/binder节点, 这个操作最终会调用到
binder_open(),最终会创建binder_proc这个对象,他是一个管理数据的记录体(每个进程都有独立的记录体)。然后对proc对象进行各种初始化操作,最后将它加入到Binder的全局管理中。目前,Binder驱动已经为用户创建了一个他自己的binder_proc实体,之后用户对Binder设备的操作将以这个对象为基础。
binder_mmap上层用户调用
mmap()函数之后,最终会调用到binder驱动的binder_mmap。mmap()可以将设备的指定内存块映射到应用程序的内存空间中。那么它有什么用呢?假设有两个进程A和B
- 对于A进程,当他调用
binder_open,mmap()得到一个虚拟内binder_open存的地址,这个地址经过内存转换(分段,分页转换)之后会指向一个确定的物理内存地址。 - 对于binder驱动而言,它的内部有一个指针
binder_proc->buffer指向一个虚拟内存地址。而这个虚拟内存地址经过转换之后会和进程A指向同一个物理内存地址。 - 这样binder驱动就和进程A拥有了共享的内存地址块。
- binder驱动可以通过
copy_from_user()将进程B中的部分数据复制到binder_proc->buffer指向的内存空间。这样,只通过一次复制,我们就实现了A进程和B进程之间数据的共享。
- 对于A进程,当他调用
binder_ioctl
binder_ioctl提供了许多命令,它承载了Binder驱动的大部分业务。
说明 命令 可以通过此命令向binder读取或写入数据 BINDER_WRITE_READ 设置支持的最大线程数 BINDER_SET_MAX_THREADS ServiceManager专用,将自己设置为Binder的总管。 BINDER_SET_CONTEXT_MGR 通知Binder线程退出,每一个线程退出时都应该通知Binder驱动 BINDER_THREAD_EXIT 获取Binder版本号 BINDER_VERSION ServiceManager
SM有点类似于网络中的DNS服务器。SM的句柄(handle)是固定的为0;
SM必须保证它在binder驱动被使用之前就要启动。所以,它的启动是在init.rc被解析时启动的。SM本身也是一个BinderServer。
int main(int argc, char **argv) { struct binder_state *bs; void *svcmgr = BINDER_SERVICE_MANAGER; bs = binder_open(128*1024); if (binder_become_context_manager(bs)) { LOGE("cannot become context manager (%s)\n", strerror(errno)); return -1; } svcmgr_handle = svcmgr; binder_loop(bs, svcmgr_handler); return 0; }
SM流程:
给变量svcmgr赋初值,宏定义
#define BINDER_SERVICE_MANAGER ((void*) 0)调用binder_open打开Binder设备。进行初始化。
bs = binder_open(128*1024);struct binder_state *binder_open(unsigned mapsize) { struct binder_state *bs; bs = malloc(sizeof(*bs)); ... bs->fd = open("/dev/binder", O_RDWR);//打开binder驱动节点 ... bs->mapsize = mapsize; //将binder驱动指定内存地址的部分空间映射到SM进程所在内存空间 bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); ... return bs; fail_map: close(bs->fd); fail_open: free(bs); return 0; }
将自己设置为Binder大管家。
int binder_become_context_manager(struct binder_state *bs) { return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); }可以看到,像binder驱动发送了
BINDER_SET_CONTEXT_MGRSM启动很早,可以保证自己是第一个向binder驱动发送命令注册为binder管家的。
进入主循环。
binder_loop(bs, svcmgr_handler);for (;;) { bwr.read_size = sizeof(readbuf); bwr.read_consumed = 0; bwr.read_buffer = (unsigned) readbuf; res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);//从binder驱动中获取消息 if (res < 0) { fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno)); goto fail; } res = binder_parse(bs, reply, readbuf, bwr.read_consumed, 0);//处理读到的消息 if (res == 0) return 0; if (res < 0) goto fail; }循环就是典型的消息轮询机制了
- 从消息队列中不断读取消息
- 如果是退出命令,则退出循环;如果消息为空,就继续读取或者进入阻塞;如果读到了消息,就处理消息。
SM的主要功能就是
- 注册:当一个Binder Server被创建之后,需要将自身的名称、句柄告知SM进行注册
- 查询:其它应用程序可以向SM发起查询请求,查询某个Binder Server对应的句柄。
SM中维持着一个全局的list数据结构,保存所有Binder Server的注册信息。查询是直接从这个list中进行查询即可。
注册的话,需要先在SM中查询是否已有对应节点。如果有就不需要再注册,否则需要创建一个新的节点来记录这个Binder Server的对应信息,并保存在list中。
Binder 上层的设计思路
现在,我们如何从Binder Client中获取SM这个Binder Server呢?
整体流程也就这几步:
- 打开binder驱动
- 调用mmap映射内存空间
- 通过binder驱动向SM发送请求(SM的句柄为0)
- 获得结果
考虑:如果每次应用程序每次使用binder都要打开binder驱动,映射空间,那么他消耗的资源会越来越多,根本吃不消。所以我们要求每个进程只能打开一次binder,映射一次空间,其中进程中的所有线程要共享这一资源。那么就需要一个对象来管理。所以出现了一个对象ProcessState。
并且所有线程都要自由访问binder驱动(Binder通讯进行时是阻塞式的), 它们之间就需要进行同步处理,所以实际上与Binder驱动进行交互的是IPCThreadState
现在我们可以获取SM了,我们可以通过发送BINDER_WRITE_READ等Binder支持的命令来与binder驱动交互,从而一步一步获得SM提供的服务。然而这样做实在太过繁琐了,那怎么办?当然是封装,这些与binder驱动的交互封装起来 对上层透明。
我们知道SM主要功能有两个
getServiceaddService那么我们就设计这样一个接口,将SM提供的功能定义出来。public interface IServiceManager { public IBinder getService(String name) throws RemoteException; public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException; public String[] listServices() throws RemoteException; static final String descriptor = "android.os.IServiceManager"; ... }我们再创建一个代理类ServiceManagerProxy来远程代理ServiceManager(注意这里的代理是指代理SM这个概念的功能)的功能。就像买火车票一样,你去火车站售票窗口可以买,但是太远了。 你家附近就有一个售票代理点。 那么这个售票代理点就要和火车站的服务内容保持一致,可以查票,买票,退票。
所以ServiceManagerProxy需要继承自IServiceManager
class ServiceManagerProxy implements IServiceManager { private IBinder mRemote; public ServiceManagerProxy(IBinder remote) { mRemote = remote; } public IBinder asBinder() { return mRemote; } public IBinder getService(String name) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); IBinder binder = reply.readStrongBinder(); reply.recycle(); data.recycle(); return binder; } public void addService(String name, IBinder service) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); data.writeStrongBinder(service); mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); reply.recycle(); data.recycle(); } ... }使用ServiceManagerProxy来代理ServiceManager的功能可能会让某些人迷茫,native层是ServiceManager,怎么到了Java层变成了ServiceManagerProxy? 所以我们可以在ServiceManagerProxy外面再包上一层,就取名为ServiceManager
public final class ServiceManager { private static final String TAG = "ServiceManager"; private static IServiceManager sServiceManager; private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>(); public static void initServiceCache(Map<String, IBinder> cache) { if (sCache.size() != 0) { throw new IllegalStateException("setServiceCache may only be called once"); } sCache.putAll(cache); } private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager; } public static IBinder getService(String name) { try { IBinder service = sCache.get(name);//首先从缓存中查找 if (service != null) { return service; } else { return getIServiceManager().getService(name); } } catch (RemoteException e) { Log.e(TAG, "error in getService", e); } return null; }public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service);
} catch (RemoteException e) {
Log.e(TAG, “error in addService”, e);
}
}这时,我们就可以直接使用
ServiceManager.getService(name);来获取Binder Server。我们来看看获得SM的调用过程
ServiceManager中全都是静态方法,所以可以直接调用getService方法。public static IBinder getService(String name) { try { IBinder service = sCache.get(name); if (service != null) { return service; } else { return getIServiceManager().getService(name); } } catch (RemoteException e) { Log.e(TAG, "error in getService", e); } return null; } private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } sServiceManager =ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager; }
getService会先充cache中查找本地有没有这个IBinder对象。没有的话就会调用
ServiceManagerNative.asInterface(BinderInternal.getContextObject());来获取。public abstract class ServiceManagerNative extends Binder implements IServiceManager{ static public IServiceManager asInterface(IBinder obj){ if (obj == null) { return null; } IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor); if (in != null) { return in; } return new ServiceManagerProxy(obj); } public ServiceManagerNative(){ attachInterface(this, descriptor); } ... public IBinder asBinder(){ return this; } }可以看到 asInterface这个方法先调用了queryLocalInterface查询本地是否有这个对象,有的话将这个对象转为IServiceManager类型的对象返回,没有的话 new 了一个ServiceManagerProxy对象,并且使用ServiceManagerProxy中的成员变量mRemote来记录这个IBinder对象。其中ServiceManagerProxy是继承自IServiceManager接口的,所以可以直接返回。
那么这里的关键就是这个
IBinder obj了,它是从哪来的呢? 查看调用流程会发现调用BinderInternal.getContextObject()获得了IBinder对象,更进去会发现这是一个native的方法。说明它是和底层Binder驱动交互的,我们先不管他。获得了IServiceManager的实现对象ServiceManagerProxy,调用了它的getService方法。
public IBinder getService(String name) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);//最关键的一句 IBinder binder = reply.readStrongBinder(); reply.recycle(); data.recycle(); return binder; }data,reply都是Parcel对象用来装载数据。 整体流程就是,将IServiceManager的描述符以及需要获得的Binder Server的名称放入data,接着调用mRote的transact方法,线程挂起,调用native层代码。等待数据返回之后,调用reply接受数据,从reply中读取到IBinder对象。 所以整个流程最关键的一句就是
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);GET_SERVICE_TRANSATION是一个常量
int GET_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION; int FIRST_CALL_TRANSACTION = 0x00000001;而在Service_manager.c中的业务代码定义(实际定义在binder.h文件中)
enum { SVC_MGR_GET_SERVICE = 1, SVC_MGR_CHECK_SERVICE, SVC_MGR_ADD_SERVICE, SVC_MGR_LIST_SERVICES, };这样,客户端功能就和服务端统一了。
再探native
上一小节,我们有两个地方调用到了native层去,分别是
BinderInternal.getContextObject()和mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);BinderInternal是获取到IBinder对象的。而mRemote实际就是一个IBinder对象。
所以IBinder接口至少有如下方法
public interface IBinder { public IInterface queryLocalInterface(String descriptor); public boolean transact(int code, Parcel data, Parcel reply, int flags)throws RemoteException; ... }而BinderInternal至少有如下方法
public class BinderInternal { public static final native IBinder getContextObject(); ... }其中BinderInternal的getContextObject方法native实现代码如下
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) { sp<IBinder> b = ProcessState::self()->getContextObject(NULL); return javaObjectForIBinder(env, b); }可以看到,它调用了ProcessState的getContextObject方法,然后将ProcessState创建的对象转换为IBinder对象返给Java层。
IBinder是一个接口,那么在Java层肯定有有类实现了它,这个类就是IBinderProxy,而在natice层继承了IBinder接口的就是BpBinder。 实际上
ProcessState::self()->getContextObject(NULL);调用返回的就是一个BpBinder对象final class BinderProxy implements IBinder { public native String getInterfaceDescriptor() throws RemoteException; public native boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException; ... }transact方法是一个native方法,native层对应的实现在android_util_binder中
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException { ... Parcel* data = parcelForJavaObject(env, dataObj); ... Parcel* reply = parcelForJavaObject(env, replyObj); ... IBinder* target = (IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject); ... //调用了native层IBinder的transact方法 status_t err = target->transact(code, *data, reply, flags); ... if (err == NO_ERROR) { return JNI_TRUE; } else if (err == UNKNOWN_TRANSACTION) { return JNI_FALSE; } signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/); return JNI_FALSE; }其中data以及reply是将Java层的Parcel转化为native层的Parcel容器对象。 然后调用了native层IBinder的transact方法。而native层的IBinder接口实现为BpBinder,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) { status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); if (status == DEAD_OBJECT) mAlive = 0; return status; } return DEAD_OBJECT; }可以看到,最后还是调用了IPCThreadState的transact方法
所以饶了一大圈,最后实现的还是IPCThreadState和ProcessState。
ProcessState和IPCThreadState
ProcessState的主要职责在于:
保证一个进程只有一个ProcessState对象存在,并且在创建对象时做打开binder驱动以及mmap内存映射。
向上层提供服务
与IPCThreadState各司其职
第一个很好解决,采用类似Java中的单例即可。
sp<ProcessState> ProcessState::self() { if (gProcess != NULL) return gProcess; AutoMutex _l(gProcessMutex); if (gProcess == NULL) gProcess = new ProcessState; return gProcess; }如果当前进程有ProcessState实例,则直接返回实例。否则创建这个实例。
ProcessState的构造函数
ProcessState::ProcessState() : mDriverFD(open_driver()), mVMStart(MAP_FAILED) , mManagesContexts(false), mBinderContextCheckFunc(NULL) , mBinderContextUserData(NULL), mThreadPoolStarted(false) , mThreadPoolSeq(1) { if (mDriverFD >= 0) { #if !defined(HAVE_WIN32_IPC) mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); ... } }其中 ,调用open_driver()打开binder驱动。调用mmap来将binder驱动部分空间映射到当前进程的内存空间。
前面我们看到Java层调用了
BinderInternal.getContextObject()来获取IBinder对象,而这个方法又调用了native方法ProcessState::self()->getContextObject(NULL);sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller) { return getStrongProxyForHandle(0); }sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) { sp<IBinder> result;//需要返回的IBinder AutoMutex _l(mLock); //查找一个vector表。这个表保存了这个进程中已经建立的Binder相关信息 handle_entry* e = lookupHandleLocked(handle);//如果是SM,Handle为0 //如果verctor中没有找到节点,会自动创建一个。所以e一般不会为null if (e != NULL) { IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { b = new BpBinder(handle); //BpBinder创建 e->binder = b; if (b) e->refs = b->getWeakRefs(); result = b; } else { result.force_set(b); e->refs->decWeak(this); } } return result; }IPCThreadState需要保证线程单实例,所以他采取了TLS (Thread Loacl Storage) 机制来保证线程单实例。
IPCThreadState* IPCThreadState::self() { if (gHaveTLS) { restart: const pthread_key_t k = gTLS; IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k); if (st) return st; return new IPCThreadState; } if (gShutdown) return NULL; pthread_mutex_lock(&gTLSMutex); if (!gHaveTLS) { if (pthread_key_create(&gTLS, threadDestructor) != 0) { pthread_mutex_unlock(&gTLSMutex); return NULL; } gHaveTLS = true; } pthread_mutex_unlock(&gTLSMutex); goto restart; }
IPCThreadState的构造函数
IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), mMyThreadId(androidGetTid()), mStrictModePolicy(0), mLastTransactionBinderFlags(0) { pthread_setspecific(gTLS, this); clearCaller(); mIn.setDataCapacity(256); mOut.setDataCapacity(256); }IPCThreadState主要负责与binder驱动交互,所以他的transact方法非常重要
status_t IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ ... }各个参数:
handle:目前调用的是SM,所以为0; 即在ProcessState中构建BpBinder时的mHandle
code:从Java层传递过来的,为
GET_SERVICE_TRANSACTION。data:从Java层传递过来的,Java层对data的操作为:
data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name);reply:Parcel类型的变量。
flags: Java层传递过来的,目前为0;
- 先检查数据是否异常,然后将flags置为TF_ACCEPT_FDS
status_t err = data.errorCheck(); flags |= TF_ACCEPT_FDS;各个flag的意义
flags 意义 TF_ONE_WAY 表示当前业务是异步的。不需要返回 TF_ROOT_OBJECT 所包含的内容是根对象 TF_STATUS_CODE 所包含的内容是32位状态值 TF_ACCEPT_FDS 允许回复中包含文件描述符 接下来,trasact将数据按照binder协议约定的格式进行打包.
if (err == NO_ERROR) { LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(), (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY"); err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); }进行打包的函数是writeTransactionData。这个方法只是将数据整理打包,数据被存储在mOut中。
调用了waitForResponse
if ((flags & TF_ONE_WAY) == 0) {//判断上面的flag克制,代码会走到调用waitForResponse ... if (reply) { err = waitForResponse(reply); } else { Parcel fakeReply;//做一个假的reply,调用waitForResponse err = waitForResponse(&fakeReply); } ... }调用了talkWithDriver
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) { int32_t cmd; int32_t err; while (1) {//循环等待响应数据 if ((err=talkWithDriver()) < NO_ERROR) break;//处理与binder驱动的交互 err = mIn.errorCheck(); if (err < NO_ERROR) break;//出现异常就退出循环 if (mIn.dataAvail() == 0) continue; //mIn中没有数据的话,继续循环 cmd = mIn.readInt32();//从mIn中读取响应 //接下来是一个switch,根据返回的响应来决定如何处理,暂时先不看 ... } }看看talkWithDriver的具体实现
status_t IPCThreadState::talkWithDriver(bool doReceive) { LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened"); 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 = (long unsigned int)mOut.data(); if (doReceive && needRead) { bwr.read_size = mIn.dataCapacity(); bwr.read_buffer = (long unsigned int)mIn.data(); } else { bwr.read_size = 0; bwr.read_buffer = 0; } ... #if defined(HAVE_ANDROID_OS) //调用ioctl函数与binder驱动交互 if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) err = NO_ERROR; else err = -errno; #else err = INVALID_OPERATION; #endif IF_LOG_COMMANDS() { alog << "Finished read/write, write size = " << mOut.dataSize() << endl; } } while (err == -EINTR); IF_LOG_COMMANDS() { alog << "Our err: " << (void*)err << ", write consumed: " << bwr.write_consumed << " (of " << mOut.dataSize() << "), read consumed: " << bwr.read_consumed << endl; } if (err >= NO_ERROR) { if (bwr.write_consumed > 0) { if (bwr.write_consumed < (ssize_t)mOut.dataSize()) mOut.remove(0, bwr.write_consumed); else mOut.setDataSize(0); } if (bwr.read_consumed > 0) { mIn.setDataSize(bwr.read_consumed); mIn.setDataPosition(0); } IF_LOG_COMMANDS() { TextOutput::Bundle _b(alog); alog << "Remaining data size: " << mOut.dataSize() << endl; alog << "Received commands from driver: " << indent; const void* cmds = mIn.data(); const void* end = mIn.data() + mIn.dataSize(); alog << HexDump(cmds, mIn.dataSize()) << endl; while (cmds < end) cmds = printReturnCommand(alog, cmds); alog << dedent; } return NO_ERROR; } return err; }在于Binder驱动进行交互中,Binder Client端会进入睡眠等待。
Binder驱动根据命令从用户空间复制数据,并且将睡眠的ServiceManger唤醒。 ServiceManager会从Binder驱动中通过消息模型读取命令,与Binder驱动交互。
ServiceManager根据读取到的数据进行处理,并将处理结果写到binder_write_read数据结构中(其中包含了查询的BinderServer的handle),然后调用ioctl与binder驱动交互,Binder驱动把数据写到mIn中,将数据从Binder Server端复制到Binder Client端。
将mIn中的数据封装到reply中,经过一系列返回, 回到Java端的ServiceManagerProxy中得getService()方法中
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); IBinder binder = reply.readStrongBinder();这个方法native实现是在Parcel的native实现中中
sp<IBinder> Parcel::readStrongBinder() const { sp<IBinder> val; unflatten_binder(ProcessState::self(), *this, &val); return val; }unflatten_binder的实现
status_t unflatten_binder(const sp<ProcessState>& proc, const Parcel& in, sp<IBinder>* out) { const flat_binder_object* flat = in.readObject(false); if (flat) { //type这个属性在Service Server封装时会判断,在同一个进程时type属性为BINDER_TYPE_BINDER,不同进程时为BINDER_TYPE_HANDLE。即同一个进程直接给了要查询的binder的引用,不同进程时给的binder的句柄 switch (flat->type) { case BINDER_TYPE_BINDER://同一个进程type类型 *out = static_cast<IBinder*>(flat->cookie); return finish_unflatten_binder(NULL, *flat, in); case BINDER_TYPE_HANDLE://不同的进程type类型 *out = proc->getStrongProxyForHandle(flat->handle); return finish_unflatten_binder( static_cast<BpBinder*>(out->get()), *flat, in); } } return BAD_TYPE; }调用了getStrongProxyForHandle
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) { sp<IBinder> result; //先从本地记录查找有没有。 handle_entry* e = lookupHandleLocked(handle); if (e != NULL) { IBinder* b = e->binder; //当本地没有这个IBinder或者给它增加引用失败,就根据handle创建一个BpBinder if (b == NULL || !e->refs->attemptIncWeak(this)) { 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; }至此,通过getservice方法成功获得了ServiceManager的本地代理对象。
总结:
ServiceManagerProxy
ServiceManagerProxy是SM在本地的代理端。
当一个BinderServer在启动的时候,会在SM端注册自己,SM会记录它的name和handle。当调用者需要使用一个BinderServer时,通常只知道它的name。所以SM提供了查询服务来获得某个Server的handle。而SM本身也是一个Server,它的handle是固定的为0。
获得SM的本地代理对象需要调用BinderInternal.getObjectContext()来获取SM的BpBinder。在Java层就是ServiceManagerProxy
ProcessState和IPCThreadState
ProcessState负责处理与进程有关的业务,IPCThreadState负责线程有关的业务。他们是Android系统为了方便上层使用binder所封装的两个实现类.
ProcessState主要负责打开binder驱动,mmap映射binder驱动内存空间。而具体的与binder驱动的交互就交给了IPCThreadState来处理。
上面的例子中,从Java层的IBinder.transact调用到native层的IPCThreadState的transact(),然后到waitForResponse进入循环——直到收到SM端的回复之后跳出循环,然后再一层一层返回Java端。
ServiceManager
SM在系统启动时就启动了,然后将自己注册为BinderServer的管家。并在最后一次ioctl操作中进入睡眠状态,直到有Client端发起请求,然后被binder驱动唤醒。唤醒之后SM分为两条线进行
- SM执行read操作,把具体的请求读取出来,然后掉binder_parse进行解析。将处理的结果通过ioctl操作返回给binder驱动。
- Client端在执行玩write请求,执行read请求时进入了睡眠状态,直到binder驱动收到了SM的回复后将Client端唤醒。Client端将回复的结果封装到Parcel类型的reply中,然后层层返回到Java端。
最后将返回的IBInder通过asInterface进行包装。例如返回的SM的IBInder会通过调用ServiceManagerNative的asInterface方法包装成ServiceManagerProxy对象。

4227

被折叠的 条评论
为什么被折叠?



