Android系统RPC与Binder

一、RPC与IPC关系

    Binder机制对于Android系统学习就犹如根文件系统挂载部分对于Linux内核学习;是一座不得不翻越的大山(指其复杂程度与重要性)。

1.RPC基本流程

    RPC在调用一个远程过程后,自己进入等待状态,传往远程过程的参数包括过程参数,返回参数包括执行结果;当收到包括执行结果的消息后,本地进程从消息中取得结果,调用进程重新开始执行。在服务器一方,有一个程序在等待调用,当有一个调用到达时,服务器进程取得进程参数,计算结果,然后返回结果。

    调用可以同步的也可以是异步的;服务器可以创建一个线程来接收用户请求,也可以自己来接收用户请求。

2.二者关系

相同点:二者都可以用于进程间;

不同点:RPC强调的是调用、即一个进程直接调用另外一个进程中的方法,而IPC仅仅完成进程间的互通信、没有函数调用功能。

总结:RPC其实就是添加了进程间函数调用功能的IPC。

二、Android系统RPC与Binder的关系

    Android系统中的Binder为IPC的一种实现方式,为Android系统RPC机制提供底层支持;其他常见的RPC还有COM组件、CORBA架构等。不同之处在于Android的RPC并不需要实现不同主机或不同操作系统间的远程调用,所以、它属于一个轻量级的RPC。

总结:Android系统的RPC = Binder进程间通信 + 在Binder基础上建立起来的进程间函数调用机制。

三、Android系统RPC实现

1.基本原理

a)服务端调用Binder驱动;并开启线程,反复调用Binder驱动的读接口、服务端继承Bnxxx进而继承BBinder的处理函数和Binder驱动的写接口,其中读接口会阻塞。

b)客户端通过Bpxxx继承Bpbinder调用Binder驱动;并开启线程,首先调用Binder驱动写接口、唤醒服务端,然后客户端调用Binder驱动读接口、并阻塞,服务器端处理完后调用写接口、唤醒阻塞中的客户端;如此,完成调用逻辑。

JAVA层AIDL——AIDL对Binder的使用进行了封装,可以让开发者方便的进行方法的远程调用。

2.具体实现

Binder负责IPC,主要就是Binder驱动;

RPC机制的的实现由如下组件完成:Client、Server、Service Manager。

下边着重分析上处组件。

3.Server服务组件

创建一个线程来接收、处理用户请求,发送执行结果:

sp<ProcessState> proc(ProcessState::self()); //打开Binder设备

ProcessState::self()->startThreadPool(); //开启监听线程

IPCThreadState::self()->joinThreadPool(); //将线程加入,loop等待客户端命令

talkWithDriver();  //接收/发送数据

executeCommand();  //指令处理

关键代码流程:

frameworks/native/libs/binder/IPCThreadState.cpp

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void IPCThreadState::joinThreadPool(bool isMain){  
  2.   do {  
  3.     result = talkWithDriver();  //接收/发送数据  
  4.     result = executeCommand(cmd); //指令处理  
  5.   }while (result != -ECONNREFUSED && result != -EBADF);  
  6. }  
  7. //接收/发送数据  
  8. status_t IPCThreadState::talkWithDriver(bool doReceive){  
  9.   binder_write_read bwr;  
  10.   bwr.write_size = outAvail;  
  11.   bwr.write_buffer = (long unsigned int)mOut.data();  
  12.   if (doReceive && needRead) {  
  13.     bwr.read_size = mIn.dataCapacity();  
  14.     bwr.read_buffer = (long unsigned int)mIn.data();  
  15.   } else {  
  16.     bwr.read_size = 0;  
  17.     bwr.read_buffer = 0;  
  18.   }  
  19.   bwr.write_consumed = 0;  
  20.   bwr.read_consumed = 0;  
  21.   do {  
  22.     if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) //重要;下边会分析  
  23.       err = NO_ERROR;  
  24.   }while (err == -EINTR);  
  25. }  
  26. //指令处理  
  27. status_t IPCThreadState::executeCommand(int32_t cmd){  
  28.   switch (cmd) {  
  29.     case BR_TRANSACTION:{  
  30.       sp<BBinder> b((BBinder*)tr.cookie);  
  31.       const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);  
  32.       /* 
  33.       frameworks/native/libs/binder/Binder.cpp 
  34.       status_t BBinder::transact( 
  35.           uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ 
  36.         err = onTransact(code, data, reply, flags); 
  37.       } 
  38.       以下为Service继承Bnxxx进而继承BBinder实现的该接口,也就是实际调用的服务端的接口 
  39.       */  
  40.     }  
  41.   }  
  42. }  
4.Client客户端组件

创建一个线程来发送请求,接收执行结果:

ProcessState::self()->getContextObject(NULL);//获得ServiceManager接口

GetService();  //获得代理接口Bpxxx

remote()->transact();  //发送请求并等待结果返回

这部分先不做讨论,后边《四》中将会看到Client/Server组件调用Service Manager的例子

5.主要使用地方就是服务创建部分:

SystemServer服务——frameworks/base/cmds/system_server/library/System_init.cpp

MediaService服务——frameworks/av/media/mediaserver/Main_mediaserver.cpp

供JAVA调用——frameworks/base/core/jni/android_util_Binder.cpp

供Native调用——frameworks/native/include/binder/BinderService.cpp

四、Binder远程同步调用的实现——ServiceManager

Binder驱动在读函数中:wait_event_interruptible(thread->wait, binder_has_thread_work(thread));阻塞睡眠。

Binder驱动在写函数中:wake_up_interruptible(target_wait);唤醒另外一个进程。

该过程是实现不同进程间同步调用的关键。

1.Client和Server组件调用ServiceManager的远程接口BpServiceManager

Server端:BpServiceManager::addService

Client端:BpServiceManager::getService

BpServiceManager::addService中如下:

frameworks/native/libs/binder/IServiceManager.cpp

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. class BpServiceManager : public BpInterface<IServiceManager>{  
  2.   virtual status_t addService(const String16& name, const sp<IBinder>& service,  
  3.             bool allowIsolated){  
  4.     status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);  
  5.     /* 
  6.     模板类 
  7.     frameworks/native/include/binder/IInterface.h 
  8.     template<typename INTERFACE> 
  9.     class BpInterface : public INTERFACE, public BpRefBase{ 
  10.       public: 
  11.       BpInterface(const sp<IBinder>& remote); 
  12.     } 
  13.      
  14.     */  
  15.   }  
  16. }  

实际调用如下:

frameworks/native/libs/binder/Binder.cpp

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. status_t BpBinder::transact(  
  2.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){  
  3.   // Once a binder has died, it will never come back to life.  
  4.   if (mAlive) {  
  5.     status_t status = IPCThreadState::self()->transact(  
  6.     mHandle, code, data, reply, flags);  //mHandle就是目标,这里是0  
  7.     if (status == DEAD_OBJECT) mAlive = 0;  
  8.       return status;  
  9.   }  
  10.   return DEAD_OBJECT;  
  11. }  

frameworks/native/libs/binder/IPCThreadState.cpp

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. status_t IPCThreadState::transact(int32_t handle,  
  2.                                   uint32_t code, const Parcel& data,  
  3.                                   Parcel* reply, uint32_t flags){  
  4.   err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);  
  5.   /* 
  6.   binder_transaction_data tr; 
  7.   tr.target.handle = handle; 
  8.   tr.code = code; 
  9.   tr.flags = binderFlags; 
  10.   tr.cookie = 0; 
  11.   tr.sender_pid = 0; 
  12.   tr.sender_euid = 0; 
  13.   */  
  14.   err = waitForResponse(reply);  
  15. }  
  16. status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult){  
  17.   if ((err=talkWithDriver()) < NO_ERROR) break;  //阻塞  
  18. }  
  19. status_t IPCThreadState::talkWithDriver(bool doReceive){  
  20.   bwr.write_consumed = 0;  
  21.   if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)  
  22. }  
drivers/staging/android/binder.c
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){  
  2.   switch (cmd) {  
  3.     case BINDER_WRITE_READ: {  
  4.       ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);  
  5.       ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK); //阻塞  
  6.     }  
  7.   }  
  8. }  
  9. int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,  
  10.             void __user *buffer, int size, signed long *consumed){  
  11.   switch (cmd) {  
  12.     case BC_TRANSACTION: //一般都是这个  
  13.     case BC_REPLY: {  
  14.       struct binder_transaction_data tr;  
  15.       if (copy_from_user(&tr, ptr, sizeof(tr))) return -EFAULT;  
  16.       ptr += sizeof(tr);  
  17.       binder_transaction(proc, thread, &tr, cmd == BC_REPLY);  
  18.       break;  
  19.     }  
  20.   }  
  21. }  
  22. static void binder_transaction(struct binder_proc *proc, struct binder_thread *thread,  
  23.     struct binder_transaction_data *tr, int reply){  
  24.   struct binder_proc *target_proc;  
  25.   struct binder_thread *target_thread = NULL;  
  26.   struct binder_node *target_node = NULL;  
  27.   struct list_head *target_list;  
  28.   wait_queue_head_t *target_wait;  
  29.   if (tr->target.handle) {  
  30.   }esle{  
  31.     target_node = binder_context_mgr_node; //重要  
  32.   }  
  33.   target_proc = target_node->proc; //重要  
  34.   if (target_thread) {  
  35.   } else {  
  36.      target_list = &target_proc->todo;  //重要  
  37.      target_wait = &target_proc->wait;  //重要  
  38.   }  
  39.   //唤醒ServiceManager线程  
  40.   list_add_tail(&t->work.entry, target_list);  
  41.   list_add_tail(&tcomplete->entry, &thread->todo);  
  42.   if (target_wait)  
  43.     wake_up_interruptible(target_wait);  //唤醒ServiceManager  
  44. }  

唤醒ServiceManager并将说明需要调用的接口以及入参。

2.ServiceManager组件如何响应Client和Server组件调用过程

先补充下Service Manager进程启动过程:

frameworks/base/cmds/servicemanager/service_manager.c

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int main(int argc, char **argv){  
  2.   binder_loop(bs, svcmgr_handler);  
  3. }  
frameworks/base/cmds/servicemanager/binder.c
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void binder_loop(struct binder_state *bs, binder_handler func){  
  2.   for(;;){  
  3.     res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);  
  4.     res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);  
  5.   }  
  6. }  
drivers/staging/android/binder.c
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){  
  2.   if (bwr.read_size > 0) {  
  3.     ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);  
  4.     ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);  
  5.   }  
  6. }  
  7. static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread,  
  8.     void  __user *buffer, int size, signed long *consumed, int non_block){  
  9.   ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread)); //等待被唤醒  
  10. }  
=========================================

//被唤醒后

frameworks/base/cmds/servicemanager/service_manager.c

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int binder_parse(struct binder_state *bs, struct binder_io *bio,  
  2.                  uint32_t *ptr, uint32_t size, binder_handler func){  
  3.   switch(cmd) {  
  4.     case BR_TRANSACTION: {  
  5.       binder_send_reply(bs, &reply, txn->data, res);  
  6.     }  
  7.   }  
  8. }  
  9. void binder_send_reply(struct binder_state *bs,  
  10.                        struct binder_io *reply,  
  11.                        void *buffer_to_free,  
  12.                        int status){  
  13.   binder_write(bs, &data, sizeof(data));  
  14. }  
  15. int binder_write(struct binder_state *bs, void *data, unsigned len){  
  16.   struct binder_write_read bwr;  
  17.   int res;  
  18.   bwr.write_size = len;  
  19.   bwr.write_consumed = 0;  
  20.   bwr.write_buffer = (unsigned) data;  
  21.   bwr.read_size = 0;  
  22.   bwr.read_consumed = 0;  
  23.   bwr.read_buffer = 0;  
  24.   res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);  
  25. }  

唤醒Client或Server组件并将执行结果返回。

六、Binder驱动部分

drivers/staging/android/binder.c

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static struct file_operations binder_fops = {  
  2.   .owner = THIS_MODULE,  
  3.   .poll = binder_poll,  
  4.   .unlocked_ioctl = binder_ioctl,  //控制操作接口  
  5.   .mmap = binder_mmap, //mmap系统调用  
  6.   .open = binder_open,  //打开接口  
  7.   .flush = binder_flush,  
  8.   .release = binder_release,  //关闭接口  
  9. };  
  10.   
  11. static struct miscdevice binder_miscdev = {  
  12.   .minor = MISC_DYNAMIC_MINOR,  
  13.   .name = "binder",  
  14.   .fops = &binder_fops  
  15. };  
  16.   
  17. static int __init binder_init(void){  
  18.   int ret;  
  19.   binder_proc_dir_entry_root = proc_mkdir("binder", NULL);  
  20.   if (binder_proc_dir_entry_root)  
  21.     binder_proc_dir_entry_proc = proc_mkdir("proc", binder_proc_dir_entry_root);  
  22.   ret = misc_register(&binder_miscdev);  //注册设备并创建设备节点  
  23.   if (binder_proc_dir_entry_root) {  
  24.     create_proc_read_entry("state", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_state, NULL);  
  25.     create_proc_read_entry("stats", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_stats, NULL);  
  26.     create_proc_read_entry("transactions", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_transactions, NULL);  
  27.     create_proc_read_entry("transaction_log", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_transaction_log, &binder_transaction_log);  
  28.     create_proc_read_entry("failed_transaction_log", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_transaction_log, &binder_transaction_log_failed);  
  29.   }  
  30.   return ret;  
  31. }  
  32.   
  33. device_initcall(binder_init);  

七、一些dome

1.Native层的binder应用:Android Binder机制的Native应用

2.Native层的binder双向调用:Android Binder机制的Native应用—双向通信

3.JAVA层的binder实例:Android Service学习之AIDL, Parcelable和远程服务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值