Binder服务获取和调用的过程C++篇

111 阅读3分钟

好的,我来用“打电话”的比喻,把整个Binder服务获取和调用的过程讲成一个故事,帮助你轻松理解:


故事:小明给“Hello服务中心”打电话

​1. 准备工作:安装电话线(Binder驱动初始化)​

小明(客户端)想给“Hello服务中心”打电话。首先,他得确保自己家里有电话线(Binder驱动)。于是他跑到电箱前,打开了一个叫ProcessState::self()的电闸。这个电闸一开,电话线就通上了电,小明家现在可以打电话了。


​2. 查号码本:找到“服务中心总机”(获取ServiceManager)​

接下来,小明需要知道“Hello服务中心”的电话号码。他翻开一本叫​​黄页(ServiceManager)​​的号码本,拨通了总机的号码(defaultServiceManager())。接电话的是总机的话务员(BpServiceManager),小明说:“我要找‘Hello服务中心’!”


​3. 查号服务:总机帮忙转接(getService)​

话务员在系统里查了查,回复小明:“‘Hello服务中心’的分机号是9527(Binder句柄)。”不过,这个分机号不能直接拨,得用专门的电话卡(BpBinder)才能打通。于是,总机把分机号封装成一张电话卡(reply.readStrongBinder())寄给了小明。


​4. 制作专用电话卡(interface_cast转换接口)​

小明拿到电话卡后,发现它是一张通用卡(IBinder),但他需要的是“Hello服务中心”的专用卡(IHelloService)。于是他找了一个转换器(interface_cast<IHelloService>),把通用卡塞进去。转换器“咔嚓”一声,吐出一张印着​​“Hello服务专线”​​的卡(BpHelloService),现在小明可以直拨服务了。


​5. 拨通电话:发起远程调用(sayHello)​

小明迫不及待地拨通电话,按下“呼叫”按钮(service->sayHello())。这时发生了两件事:

  • ​小明这边(客户端)​​:
    他把要说的话(Parcel data)写在一张纸条上:“请说Hello!”,塞进信封,通过电话卡(BpBinder)寄出。然后他抱着电话等待回复(阻塞等待)。
  • ​服务中心(服务端)​​:
    服务中心的电话员(BnHelloService)一直在监听电话(joinThreadPool)。突然电话响了,他接起来,拆开信封看到小明的请求,立刻在服务中心的日志本上写下一行:“第1次说Hello!”(ALOGI("server say hello :1")),然后把“收到啦!”(reply.writeInt32(0))塞回信封寄给小明。

​6. 挂断电话:收到回复​

小明终于等到回信,拆开一看是“收到啦!”,心满意足地挂断了电话。整个通话过程,小明完全不用关心服务中心在哪个城市、有多少话务员——他只需要拨通电话卡,剩下的Binder机制(就像电话系统)默默搞定了一切!


总结:Binder机制的核心角色

  • ​黄页(ServiceManager)​​:记录所有服务名称和对应的“电话卡”(Binder句柄)。
  • ​电话卡(BpBinder/BnBinder)​​:客户端持代理(BpBinder),服务端持本体(BnBinder)。
  • ​信封(Parcel)​​:用来打包数据,跨进程传递。
  • ​电话员(IPCThreadState)​​:负责接电话、读信封、调用实际方法(onTransact)。

整个过程就像打电话一样:查号码、拨通、传纸条、等回复。Binder机制让跨进程调用变得像本地调用一样简单!