o IBinder接口
IBinder接口是对跨进程的对象的抽象。普通对象在当前进程可以访问,如果希望对象能被其它进程访问,那就必须实现IBinder接口。IBinder接口可以指向本地对象,也可以指向远程对象,调用者不需要关心指向的对象是本地的还是远程。
transact是IBinder接口中一个比较重要的函数,它的函数原型如下:
virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0 ) = 0 ;
android中的IPC的基本模型是基于客户/服务器(C/S)架构的。
客户端 | 请求通过内核模块中转 | 服务端 |
如果IBinder指向的是一个客户端代理,那transact只是把请求发送给服务器。服务端的IBinder的transact则提供了实际的服务。
o 客户端
BpBinder是远程对象在当前进程的代理,它实现了IBinder接口。它的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; }
参数说明:
- code 是请求的ID号。
- data 是请求的参数。
- reply 是返回的结果。
- flags 一些额外的标识,如FLAG_ONEWAY。通常为0。
transact只是简单的调用了IPCThreadState::self()的transact,在IPCThreadState::transact中:
status_t IPCThreadState:: transact ( int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { status_t err = data.errorCheck ( ) ; flags |= TF_ACCEPT_FDS; IF_LOG_TRANSACTIONS( ) { TextOutput:: Bundle _b( alog) ; alog << "BC_TRANSACTION thr " << ( void * ) pthread_self( ) << " / hand " << handle << " / code " << TypeCode( code) << ": " << indent << data << dedent << endl; } 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) ; } if ( err != NO_ERROR) { if ( reply) reply-> setError( err) ; return ( mLastError = err) ; } if ( ( flags & TF_ONE_WAY) == 0 ) { if ( reply) { err = waitForResponse( reply) ; } else { Parcel fakeReply; err = waitForResponse( & fakeReply) ; } IF_LOG_TRANSACTIONS( ) { TextOutput:: Bundle _b( alog) ; alog << "BR_REPLY thr " << ( void * ) pthread_self( ) << " / hand " << handle << ": " ; if ( reply) alog << indent << * reply << dedent << endl; else alog << "(none requested)" << endl; } } else { err = waitForResponse( NULL, NULL) ; } return err; } status_t IPCThreadState:: waitForResponse ( Parcel * reply, status_t * acquireResult) { int32_t cmd; int32_t err; while ( 1 ) { if ( ( err= talkWithDriver( ) ) < NO_ERROR) break ; err = mIn.errorCheck ( ) ; if ( err < NO_ERROR) break ; if ( mIn.dataAvail ( ) == 0 ) continue ; cmd = mIn.readInt32 ( ) ; IF_LOG_COMMANDS( ) { alog << "Processing waitForResponse Command: " << getReturnString( cmd) << endl; } 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: { LOG_ASSERT( acquireResult != NULL, "Unexpected brACQUIRE_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) ) ; LOG_ASSERT( err == NO_ERROR, "Not enough command data for brREPLY" ) ; if ( err != NO_ERROR) goto finish; if ( reply) { if ( ( tr.flags & TF_STATUS_CODE) == 0 ) { reply-> ipcSetDataReference( reinterpret_cast( tr.data .ptr .buffer ) , tr.data_size , reinterpret_cast( tr.data .ptr .offsets ) , tr.offsets_size / sizeof ( size_t) , freeBuffer, this) ; } else { err = * static_cast( tr.data .ptr .buffer ) ; freeBuffer( NULL, reinterpret_cast( tr.data .ptr .buffer ) , tr.data_size , reinterpret_cast( tr.data .ptr .offsets ) , tr.offsets_size / sizeof ( size_t) , this) ; } } else { freeBuffer( NULL, reinterpret_cast( tr.data .ptr .buffer ) , tr.data_size , reinterpret_cast( tr.data .ptr .offsets ) , tr.offsets_size / sizeof ( 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; }
这里transact把请求经内核模块发送了给服务端,服务端处理完请求之后,沿原路返回结果给调用者。这里也可以看出请求是同步操作,它会等待直到结果返回为止。
在BpBinder之上进行简单包装,我们可以得到与服务对象相同的接口,调用者无需要关心调用的对象是远程的还是本地的。拿ServiceManager来说:
(frameworks/base/libs/utils/IServiceManager.cpp)
class BpServiceManager : public BpInterface { public: BpServiceManager( const sp& impl) : BpInterface( impl) { } ... virtual status_t addService( const String16& name, const sp& service) { Parcel data, reply; data.writeInterfaceToken ( IServiceManager:: getInterfaceDescriptor ( ) ) ; data.writeString16 ( name) ; data.writeStrongBinder ( service) ; status_t err = remote( ) -> transact( ADD_SERVICE_TRANSACTION, data, & reply) ; return err == NO_ERROR ? reply.readInt32 ( ) : err; } ... } ;
BpServiceManager实现了 IServiceManager和IBinder两个接口,调用者可以把BpServiceManager的对象看作是一个 IServiceManager对象或者IBinder对象。当调用者把BpServiceManager对象当作IServiceManager对象使 用时,所有的请求只是对BpBinder::transact的封装。这样的封装使得调用者不需要关心IServiceManager对象是本地的还是远 程的了。
客户通过defaultServiceManager函数来创建BpServiceManager对象:
(frameworks/base/libs/utils/IServiceManager.cpp)
sp< IServiceManager> defaultServiceManager( ) { if ( gDefaultServiceManager != NULL) return gDefaultServiceManager; { AutoMutex _l( gDefaultServiceManagerLock) ; if ( gDefaultServiceManager == NULL) { gDefaultServiceManager = interface_cast< IServiceManager> ( ProcessState:: self ( ) -> getContextObject( NULL) ) ; } } return gDefaultServiceManager; }
先通过ProcessState::self()->getContextObject(NULL)创建一个Binder对象,然后通过 interface_cast和IMPLEMENT_META_INTERFACE(ServiceManager, “android.os.IServiceManager”)把Binder对象包装成 IServiceManager对象。原理上等同于创建了一个BpServiceManager对象。
ProcessState::self()->getContextObject调用ProcessState::getStrongProxyForHandle创建代理对象:
sp< IBinder> ProcessState:: getStrongProxyForHandle ( int32_t handle) { sp< IBinder> result; AutoMutex _l( mLock) ; handle_entry* e = lookupHandleLocked( handle) ; 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) ) { b = new BpBinder( handle) ; e-> binder = b; if ( b) e-> refs = b-> getWeakRefs( ) ; result = b; } else { // 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) ; e-> refs-> decWeak( this) ; } } return result; }
如果handle为空,默认为context_manager对象,context_manager实际上就是ServiceManager。
o 服务端
服务端也要实现IBinder接口,BBinder类对IBinder接口提供了部分默认实现,其中transact的实现如下:
status_t BBinder:: transact ( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { data.setDataPosition ( 0 ) ; status_t err = NO_ERROR; switch ( code) { case PING_TRANSACTION: reply-> writeInt32( pingBinder( ) ) ; break ; default : err = onTransact( code, data, reply, flags) ; break ; } if ( reply != NULL) { reply-> setDataPosition( 0 ) ; } return err; }
PING_TRANSACTION请求用来检查对象是否还存在,这里简单的把 pingBinder的返回值返回给调用者。其它的请求交给onTransact处理。onTransact是BBinder里声明的一个 protected类型的虚函数,这个要求它的子类去实现。比如CameraService里的实现如下:
status_t CameraService:: onTransact ( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { // permission checks... switch ( code) { case BnCameraService:: CONNECT : IPCThreadState* ipc = IPCThreadState:: self ( ) ; const int pid = ipc-> getCallingPid( ) ; const int self_pid = getpid( ) ; if ( pid != self_pid) { // we're called from a different process, do the real check if ( ! checkCallingPermission( String16( "android.permission.CAMERA" ) ) ) { const int uid = ipc-> getCallingUid( ) ; LOGE( "Permission Denial: " "can't use the camera pid=%d, uid=%d" , pid, uid) ; return PERMISSION_DENIED; } } break ; } status_t err = BnCameraService:: onTransact ( code, data, reply, flags) ; LOGD( "+++ onTransact err %d code %d" , err, code) ; if ( err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) { // the 'service' command interrogates this binder for its name, and then supplies it // even for the debugging commands. that means we need to check for it here, using // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to // BnSurfaceComposer before falling through to this code). LOGD( "+++ onTransact code %d" , code) ; CHECK_INTERFACE( ICameraService, data, reply) ; switch ( code) { case 1000 : { if ( gWeakHeap != 0 ) { sp h = gWeakHeap.promote ( ) ; IMemoryHeap * p = gWeakHeap.unsafe_get ( ) ; LOGD( "CHECKING WEAK REFERENCE %p (%p)" , h.get ( ) , p) ; if ( h != 0 ) h-> printRefs( ) ; bool attempt_to_delete = data.readInt32 ( ) == 1 ; if ( attempt_to_delete) { // NOT SAFE! LOGD( "DELETING WEAK REFERENCE %p (%p)" , h.get ( ) , p) ; if ( p) delete p; } return NO_ERROR; } } break ; default : break ; } } return err; }
由此可见,服务端的onTransact是一个请求分发函数,它根据请求码(code)做相应的处理。
o 消息循环
服务端(任何进程都可以作为服务端)有一个线程监听来自客户端的请求,并循环处理这些请求。
如果在主线程中处理请求,可以直接调用下面的函数:
IPCThreadState:: self ( ) -> joinThreadPool( mIsMain) ;
如果想在非主线程中处理请求,可以按下列方式:
sp proc = ProcessState:: self ( ) ; if ( proc-> supportsProcesses( ) ) { LOGV( "App process: starting thread pool.\n " ) ; proc-> startThreadPool( ) ; }
startThreadPool的实现原理:
void ProcessState:: startThreadPool ( ) { AutoMutex _l( mLock) ; if ( ! mThreadPoolStarted) { mThreadPoolStarted = true ; spawnPooledThread( true ) ; } } void ProcessState:: spawnPooledThread ( bool isMain) { if ( mThreadPoolStarted) { int32_t s = android_atomic_add( 1 , & mThreadPoolSeq) ; char buf[ 32 ] ; sprintf( buf, "Binder Thread #%d" , s) ; LOGV( "Spawning new pooled thread, name=%s\n " , buf) ; sp t = new PoolThread( isMain) ; t-> run( buf) ; } }
这里创建了PoolThread的对象,实现上就是创建了一个线程。所有的线程类都要实现threadLoop虚函数。PoolThread的threadLoop的实现如下:
virtual bool threadLoop( ) { IPCThreadState:: self ( ) -> joinThreadPool( mIsMain) ; return false ; }
上述代码,简而言之就是创建了一个线程,然后在线程里调用 IPCThreadState::self()->joinThreadPool函数。
下面再看joinThreadPool的实现:
do { ... result = talkWithDriver( ) ; if ( result >= NO_ERROR) { size_t IN = mIn.dataAvail ( ) ; if ( IN < sizeof ( int32_t) ) continue ; cmd = mIn.readInt32 ( ) ; IF_LOG_COMMANDS( ) { alog << "Processing top-level Command: " << getReturnString( cmd) << endl; } result = executeCommand( cmd) ; } ... while ( ...) ;
这个函数在循环中重复执行下列动作:
- talkWithDriver 通过ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)读取请求和写回结果。
- executeCommand 执行相应的请求
在IPCThreadState::executeCommand(int32_t cmd)函数中:
- 对于控制对象生命周期的请求,像BR_ACQUIRE/BR_RELEASE直接做了处理。
- 对于BR_TRANSACTION请求,它调用被请求对象的transact函数。
按下列方式调用实际的对象:
if ( tr.target .ptr ) { sp< BBinder> b( ( BBinder* ) tr.cookie ) ; const status_t error = b-> transact( tr.code , buffer, & reply, 0 ) ; if ( error < NO_ERROR) reply.setError ( error) ; } else { const status_t error = the_context_object-> transact( tr.code , buffer, & reply, 0 ) ; if ( error < NO_ERROR) reply.setError ( error) ; }
如果tr.target.ptr不为空,就把tr.cookie转换成一个Binder对象,并调用它的transact函数。如果没有目标对象, 就调用 the_context_object对象的transact函数。奇怪的是,根本没有谁对the_context_object进行初始 化,the_context_object是空指针。原因是context_mgr的请求发给了ServiceManager,所以根本不会走到else 语句里来。
o 内核模块
android使用了一个内核模块binder来中转各个进程之间的消息。模块源代码放在binder.c里,它是一个字符驱动程序,主要通过 binder_ioctl与用户空间的进程交换数据。其中BINDER_WRITE_READ用来读写数据,数据包中有一个cmd域用于区分不同的请求:
- binder_thread_write用于发送请求或返回结果。
- binder_thread_read用于读取结果。
从binder_thread_write中调用binder_transaction中转请求和返回结果,binder_transaction的实现如下:
对请求的处理:
- 通过对象的handle找到对象所在的进程,如果handle为空就认为对象是context_mgr,把请求发给context_mgr所在的进程。
- 把请求中所有的binder对象全部放到一个RB树中。
- 把请求放到目标进程的队列