binder 传递文件描述符

为了让两个进程共享内存,也就是让他们共享同一打开的文件,这个是在binder驱动里面做的事情,当我们希望binder Client和Service端共享句柄时传递参数时必须要调用writeFileDescriptor readFileDescriptor来标识这是一个句柄值,这样binder驱动会对其做进一步的处理

看一下writeFileDescriptor

[cpp]  view plain copy print ?
  1. status_t Parcel::writeFileDescriptor(int fd)  
  2. {  
  3.     flat_binder_object obj;  
  4.     obj.type = BINDER_TYPE_FD;  
  5.     obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;  
  6.     obj.handle = fd;  
  7.     obj.cookie = (void*)0;  
  8.     return writeObject(obj, true);  
  9. }  

其实也就是写入了一个flat_binder_object结构,这样在驱动里面就需要处理这个binder

对于我们前面一个例子,client端从Service端获取fd,所以这个writeFileDescriptor是在Serivce端调用的,同样fd也是它创建的,看一下它在驱动里面相应的处理

[cpp]  view plain copy print ?
  1. case BINDER_TYPE_FD: {  
  2.     int target_fd;  
  3.     struct file *file;  
  4.   
  5.     if (reply) {  
  6.         if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {  
  7.             binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",  
  8.                 proc->pid, thread->pid, fp->handle);  
  9.             return_error = BR_FAILED_REPLY;  
  10.             goto err_fd_not_allowed;  
  11.         }  
  12.     } else if (!target_node->accept_fds) {  
  13.         binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",  
  14.             proc->pid, thread->pid, fp->handle);  
  15.         return_error = BR_FAILED_REPLY;  
  16.         goto err_fd_not_allowed;  
  17.     }  
  18.   
  19.     file = fget(fp->handle);//文件描述符的值就保存在fp->handle中  
  20.     if (file == NULL) {  
  21.         binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",  
  22.             proc->pid, thread->pid, fp->handle);  
  23.         return_error = BR_FAILED_REPLY;  
  24.         goto err_fget_failed;  
  25.     }  
  26.     target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);//在目标进程中获得一个空闲的文件描述符  
  27.     if (target_fd < 0) {  
  28.         fput(file);  
  29.         return_error = BR_FAILED_REPLY;  
  30.         goto err_get_unused_fd_failed;  
  31.     }  
  32.     task_fd_install(target_proc, target_fd, file);//把这个文件描述符和这个打开文件结构关联起来  
  33.     binder_debug(BINDER_DEBUG_TRANSACTION,  
  34.              "        fd %ld -> %d\n", fp->handle, target_fd);  
  35.     /* TODO: fput? */  
  36.     fp->handle = target_fd;//  由于这个Binder对象最终是要返回给目标进程的,所以还要修改fp->handle的值  
  37. break  
这里主要就是为其在目标进程中分配一个未使用的文件描述符,并调用task_fd_install把它和这文件关系起来。

这样,两个进程就可以共享这个文件了。

你可能感兴趣的:(binder 传递文件描述符)