Android IPC 的详细分析 一

来源:互联网 发布:openwrt多台设备mac 编辑:程序博客网 时间:2024/05/23 02:00
Binder通信简介:
  Linux系统中进程间通信的方式有:socket, named pipe,message queque, signal,share memory.Java系统中的进程间通信方式有socket, named pipe等,android应用程序理所当然可以应用JAVA的IPC机制实现进程间的通信,但我查看android的源码,在同一终端上的应用软件的通信几乎看不到这些IPC通信方式,取而代之的是Binder通信。Google为什么要采用这种方式呢,这取决于Binder通信方式的高效率。 Binder通信是通过linux的binder driver来实现的,Binder通信操作类似线程迁移(thread migration),两个进程间IPC看起来就象是一个进程进入另一个进程执行代码然后带着执行的结果返回。Binder的用户空间为每一个进程维护着一个可用的线程池,线程池用于处理到来的IPC以及执行进程本地消息,Binder通信是同步而不是异步。
  Android中的Binder通信是基于Service与Client的,所有需要IBinder通信的进程都必须创建一个IBinder接口,系统中有一个进程管理所有的system service,Android不允许用户添加非授权的System service,当然现在源码开发了,我们可以修改一些代码来实现添加底层system Service的目的。对用户程序来说,我们也要创建server,或者Service用于进程间通信,这里有一个ActivityManagerService管理JAVA应用层所有的service创建与连接(connect),disconnect,所有的Activity也是通过这个service来启动,加载的。ActivityManagerService也是加载在Systems Servcie中的。
  Android虚拟机启动之前系统会先启动service Manager进程,service Manager打开binder驱动,并通知binder kernel驱动程序这个进程将作为System Service Manager,然后该进程将进入一个循环,等待处理来自其他进程的数据。用户创建一个System service后,通过defaultServiceManager得到一个远程ServiceManager的接口,通过这个接口我们可以调用addService函数将System service添加到Service Manager进程中,然后client可以通过getService获取到需要连接的目的Service的IBinder对象,这个IBinder是Service的BBinder在binder kernel的一个参考,所以service IBinder 在binder kernel中不会存在相同的两个IBinder对象,每一个Client进程同样需要打开Binder驱动程序。对用户程序而言,我们获得这个对象就可以通过binder kernel访问service对象中的方法。Client与Service在不同的进程中,通过这种方式实现了类似线程间的迁移的通信方式,对用户程序而言当调用Service返回的IBinder接口后,访问Service中的方法就如同调用自己的函数。
  下图为client与Service建立连接的示意图:
6eff8606414ecbd07a8947c3.jpg 
  首先从ServiceManager注册过程来逐步分析上述过程是如何实现的.
  ServiceMananger进程注册过程源码分析:
  
  1.    Service Manager Process(Service_manager.c):
  2.   Service_manager为其他进程的Service提供管理,这个服务程序必须在Android Runtime起来之前运行,否则Android JAVA Vm ActivityManagerService无法注册.
  3.   int main(int argc, char **argv)
  4.   {
  5.   struct binder_state *bs;
  6.   void *svcmgr = BINDER_SERVICE_MANAGER;
  7.   bs = binder_open(128*1024); //打开/dev/binder 驱动
  8.   if (binder_become_context_manager(bs)) {//注册为service manager in binder kernel
  9.   LOGE("cannot become context manager (%s)\n", strerror(errno));
  10.   return -1;
  11.   }
  12.   svcmgr_handle = svcmgr;
  13.   binder_loop(bs, svcmgr_handler);
  14.   return 0;
  15.   }
  16.   }
  17.   });
  18.   }
  19.   }
复制代码
  首先打开binder的驱动程序然后通过binder_become_context_manager函数调用ioctl告诉Binder Kernel驱动程序这是一个服务管理进程,然后调用binder_loop等待来自其他进程的数据。BINDER_SERVICE_MANAGER是服务管理进程的句柄,它的定义是:
  /* the one magic object */
  #define BINDER_SERVICE_MANAGER ((void*) 0)
  如果客户端进程获取Service时所使用的句柄与此不符,Service Manager将不接受Client的请求。客户端如何设置这个句柄在下面会介绍。
 
  1.    CameraSerivce服务的注册(Main_mediaservice.c)
  2.   int main(int argc, char** argv)
  3.   {
  4.   sp<ProcessState> proc(ProcessState::self());
  5.   sp<IServiceManager> sm = defaultServiceManager();
  6.   LOGI("ServiceManager: %p", sm.get());
  7.   AudioFlinger::instantiate();             //Audio 服务
  8.   MediaPlayerService::instantiate();       //mediaPlayer服务
  9.   CameraService::instantiate();             //Camera 服务
  10.   ProcessState::self()->startThreadPool(); //为进程开启缓冲池
  11.   IPCThreadState::self()->joinThreadPool(); //将进程加入到缓冲池
  12.   }
  13.   CameraService。cpp
  14.   void CameraService::instantiate() {
  15.   defaultServiceManager()->addService(
  16.   String16("media.camera"), new CameraService());
  17.   }
  18.   创建CameraService服务对象并添加到ServiceManager进程中。
  19.   client获取remote IServiceManager IBinder接口:
  20.   sp<IServiceManager> defaultServiceManager()
  21.   {
  22.   if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
  23.   {
  24.   AutoMutex _l(gDefaultServiceManagerLock);
  25.   if (gDefaultServiceManager == NULL) {
  26.   gDefaultServiceManager = interface_cast<IServiceManager>(
  27.   ProcessState::self()->getContextObject(NULL));
  28.   }
  29.   }
  30.   return gDefaultServiceManager;
  31.   }
  32.   任何一个进程在第一次调用defaultServiceManager的时候gDefaultServiceManager值为Null,所以该进程会通过ProcessState::self得到ProcessState实例。ProcessState将打开Binder驱动。
  33.   ProcessState.cpp
  34.   sp<ProcessState> ProcessState::self()
  35.   {
  36.   if (gProcess != NULL) return gProcess;
  37.   AutoMutex _l(gProcessMutex);
  38.   if (gProcess == NULL) gProcess = new ProcessState;
  39.   return gProcess;
  40.   }
  41.   ProcessState::ProcessState()
  42.   : mDriverFD(open_driver()) //打开/dev/binder驱动
  43.   {
  44.   }
  45.   sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
  46.   {
  47.   if (supportsProcesses()) {
  48.   return getStrongProxyForHandle(0);
  49.   } else {
  50.   return getContextObject(String16("default"), caller);
  51.   }
  52.   }
复制代码

  Android是支持Binder驱动的所以程序会调用getStrongProxyForHandle。这里handle为0,正好与Service_manager中的BINDER_SERVICE_MANAGER一致。
 
  1. sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
  2.   {
  3.   sp<IBinder> result;
  4.   AutoMutex _l(mLock);
  5.   handle_entry* e = lookupHandleLocked(handle);
  6.   if (e != NULL) {
  7.   // We need to create a new BpBinder if there isn't currently one, OR we
  8.   // are unable to acquire a weak reference on this current one. See comment
  9.   // in getWeakProxyForHandle() for more info about this.
  10.   IBinder* b = e->binder; //第一次调用该函数b为Null
  11.   if (b == NULL || !e->refs->attemptIncWeak(this)) {
  12.   b = new BpBinder(handle);
  13.   e->binder = b;
  14.   if (b) e->refs = b->getWeakRefs();
  15.   result = b;
  16.   } else {
  17.   // This little bit of nastyness is to allow us to add a primary
  18.   // reference to the remote proxy when this team doesn't have one
  19.   // but another team is sending the handle to us。
  20.   result.force_set(b);
  21.   e->refs->decWeak(this);
  22.   }
  23.   }
  24.   return result;
  25.   }
复制代码

  第一次调用的时候b为Null所以会为b生成一BpBinder对象:
 
  1. BpBinder::BpBinder(int32_t handle)
  2.   : mHandle(handle)
  3.   , mAlive(1)
  4.   , mObitsSent(0)
  5.   , mObituaries(NULL)
  6.   {
  7.   LOGV("Creating BpBinder %p handle %d\n", this, mHandle);
  8.   extendObjectLifetime(OBJECT_LIFETIME_WEAK);
  9.   IPCThreadState::self()->incWeakHandle(handle);
  10.   }
  11.   void IPCThreadState::incWeakHandle(int32_t handle)
  12.   {
  13.   LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle);
  14.   mOut.writeInt32(BC_INCREFS);
  15.   mOut.writeInt32(handle);
  16.   }
  17.   getContextObject返回了一个BpBinder对象。
  18.   interface_cast<IServiceManager>(
  19.   ProcessState::self()->getContextObject(NULL));
  20.   template<typename INTERFACE>
  21.   inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
  22.   {
  23.   return INTERFACE::asInterface(obj);
  24.   }
复制代码

  将这个宏扩展后最终得到的是:
  
  1.   sp<IServiceManager> IServiceManager::asInterface(const sp<IBinder>& obj)
  2.   {
  3.   sp<IServiceManager> intr;
  4.   if (obj != NULL) {
  5.   intr = static_cast<IServiceManager*>(
  6.   obj->queryLocalInterface(
  7.   IServiceManager::descriptor)。get());
  8.   if (intr == NULL) {
  9.   intr = new BpServiceManager(obj);
  10.   }
  11.   }
  12.   return intr;
  13.   }
复制代码

  返回一个BpServiceManager对象,这里obj就是前面我们创建的BpBInder对象。
  client获取Service的远程IBinder接口
  以CameraService为例(camera.cpp):
  
  1.   const sp<ICameraService>& Camera::getCameraService()
  2.   {
  3.   Mutex::Autolock _l(mLock);
  4.   if (mCameraService.get() == 0) {
  5.   sp<IServiceManager> sm = defaultServiceManager();
  6.   sp<IBinder> binder;
  7.   do {
  8.   binder = sm->getService(String16("media.camera"));
  9.   if (binder != 0)
  10.   break;
  11.   LOGW("CameraService not published, waiting…");
  12.   usleep(500000); // 0.5 s
  13.   } while(true);
  14.   if (mDeathNotifier == NULL) {
  15.   mDeathNotifier = new DeathNotifier();
  16.   }
  17.   binder->linkToDeath(mDeathNotifier);
  18.   mCameraService = interface_cast<ICameraService>(binder);
  19.   }
  20.   LOGE_IF(mCameraService==0, "no CameraService!?");
  21.   return mCameraService;
  22.   }
复制代码

  由前面的分析可知sm是BpCameraService对象://应该为BpServiceManager对象
 
  1. virtual sp<IBinder> getService(const String16& name) const
  2.   {
  3.   unsigned n;
  4.   for (n = 0; n < 5; n++){
  5.   sp<IBinder> svc = checkService(name);
  6.   if (svc != NULL) return svc;
  7.   LOGI("Waiting for sevice %s…\n", String8(name).string());
  8.   sleep(1);
  9.   }
  10.   return NULL;
  11.   }
  12.   virtual sp<IBinder> checkService( const String16& name) const
  13.   {
  14.   Parcel data, reply;
  15.   data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
  16.   data.writeString16(name);
  17.   remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
  18.   return reply.readStrongBinder();
  19.   }
  20.   这里的remote就是我们前面得到BpBinder对象。所以checkService将调用BpBinder中的transact函数:
  21.   status_t BpBinder::transact(
  22.   uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  23.   {
  24.   // Once a binder has died, it will never come back to life.
  25.   if (mAlive) {
  26.   status_t status = IPCThreadState::self()->transact(
  27.   mHandle, code, data, reply, flags);
  28.   if (status == DEAD_OBJECT) mAlive = 0;
  29.   return status;
  30.   }
  31.   return DEAD_OBJECT;
  32.   }
  33.   mHandle为0,BpBinder继续往下调用IPCThreadState:transact函数将数据发给与mHandle相关联的Service Manager Process。
  34.   status_t IPCThreadState::transact(int32_t handle,
  35.   uint32_t code, const Parcel& data,
  36.   Parcel* reply, uint32_t flags)
  37.   {
  38.   if (err == NO_ERROR) {
  39.   LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
  40.   (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
  41.   err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
  42.   }
  43.   if (err != NO_ERROR) {
  44.   if (reply) reply->setError(err);
  45.   return (mLastError = err);
  46.   }
  47.   if ((flags & TF_ONE_WAY) == 0) {
  48.   if (reply) {
  49.   err = waitForResponse(reply);
  50.   } else {
  51.   Parcel fakeReply;
  52.   err = waitForResponse(&fakeReply);
  53.   }
  54.   return err;
  55.   }
复制代码

  通过writeTransactionData构造要发送的数据
  
  1.    status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
  2.   int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
  3.   {
  4.   binder_transaction_data tr;
  5.   tr.target.handle = handle; //这个handle将传递到service_manager
  6.   tr.code = code;
  7.   tr.flags = bindrFlags;
  8.   }
复制代码

  waitForResponse将调用talkWithDriver与对Binder kernel进行读写操作。当Binder kernel接收到数据后,service_mananger线程的ThreadPool就会启动,service_manager查找到CameraService服务后调用binder_send_reply,将返回的数据写入Binder kernel,Binder kernel.
  
  1. status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
  2.   {
  3.   int32_t cmd;
  4.   int32_t err;
  5.   while (1) {
  6.   if ((err=talkWithDriver()) < NO_ERROR) break;
  7.   }
  8.   status_t IPCThreadState::talkWithDriver(bool doReceive)
  9.   {
  10.   #if defined(HAVE_ANDROID_OS)
  11.   if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
  12.   err = NO_ERROR;
  13.   else
  14.   err = -errno;
  15.   #else
  16.   err = INVALID_OPERATION;
  17.   #endif
  18.   }
复制代码

  通过上面的ioctl系统函数中BINDER_WRITE_READ对binder kernel进行读写。

文章出处 http://www.eoeandroid.com/thread-160838-1-1.html

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电脑被老友重装系统搞坏了怎么办 vivo手机听筒声音小怎么办 小孩调皮幼儿园不收怎么办 小孩听力残疾幼儿园不收怎么办 幼儿园不收外省小孩怎么办 孩子刚上幼儿园哭闹老师怎么办 孕妇糖耐指标高怎么办 貂蝉经常没蓝怎么办 儿童声导抗c型怎么办 酱牛肉不烂怎么办拯救 卤牛肉一切就碎怎么办 牛肉煮的太烂了怎么办 牛肉卤的太烂怎么办 牛肉炖得太软怎么办 牛肉炖的很硬怎么办 牛肉做的有点硬怎么办 牛肉做老了还能怎么办 牛肉粒 炒老了怎么办 牛肉炖出来很硬怎么办 煮的牛肉太硬怎么办 在产蛋鸡体重偏轻怎么办 产蛋鸡不上高峰怎么办 蛋鸡天热下蛋少怎么办 成年鸡嗉子鼓涨怎么办 黄牛拼失败了钱怎么办 磁力泥粘衣服上怎么办 鼻涕泥弄衣服上怎么办 水晶橡皮泥弄在衣服上怎么办 橡皮泥弄到衣服上怎么办 橡皮泥弄在衣服上怎么办 磁力泥弄衣服上怎么办 苹果7p按键坏了怎么办 苹果手机内存满了怎么办 来微信消息手机上面没提示怎么办 苹果手机储存空间满了怎么办 苹果六储存满了怎么办视频 微信听筒没声音怎么办 苹果手机有电自动关机怎么办 白玉蜗牛生蛋了怎么办 农民工工资拖欠怎么办没有合同 公司拖欠员工工资没签合同怎么办