Android IPC有关的问题

  1.文件描述符是如何在进程之间传递的?

       我们知道文件描述符,就像虚拟内存的地址一样,是进程私有的资源。在一个进程中文件描 述符,在另外一个进程中,可能是无效的,也可能是对应另外一个文件。 Android却可以把文件描述符从一个进程传到另外一个进程。第一次发现这种情况时,让我感到很惊奇,所以花了点时间去研究。看明白之后,发现其实现也 很简单:

Java代码:
  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);

复制代码

       在对文件描述符打包时,把对象的类型设置为BINDER_TYPE_FD。
       在binder的内核模块binder_transaction函数中,我们可以看:

Java代码:
  1. case BINDER_TYPE_FD: {
  2. int target_fd;
  3. struct file *file;

  4. if (reply) {
  5. if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
  6. binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",
  7. proc->pid, thread->pid, fp->handle);
  8. return_error = BR_FAILED_REPLY;
  9. goto err_fd_not_allowed;
  10. }
  11. } else if (!target_node->accept_fds) {
  12. binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",
  13. proc->pid, thread->pid, fp->handle);
  14. return_error = BR_FAILED_REPLY;
  15. goto err_fd_not_allowed;
  16. }

  17. file = fget(fp->handle);
  18. if (file == NULL) {
  19. binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",
  20. proc->pid, thread->pid, fp->handle);
  21. return_error = BR_FAILED_REPLY;
  22. goto err_fget_failed;
  23. }
  24. target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
  25. if (target_fd < 0) {
  26. fput(file);
  27. return_error = BR_FAILED_REPLY;
  28. goto err_get_unused_fd_failed;
  29. }
  30. task_fd_install(target_proc, target_fd, file);
  31. binder_debug(BINDER_DEBUG_TRANSACTION,
  32. " fd %ld -> %d\n", fp->handle, target_fd);
  33. /* TODO: fput? */
  34. fp->handle = target_fd;
  35. } break;
复制代码

       这里如果是文件描述符,就在目标进程中重新打开同一个文件了(虽然打开的是同一个文件,但目标进程拿到的文件描述符可能不相同)。

        2.Receiver是如何工作的?

       大家对Service的工作原理应该比较熟悉,先通过服务名称从 ServiceManager获取一个Binder,然后通过Binder去调用服务相应的函数。由客户端主动发起请求,这是典型是C/S模型。而 Receiver则是服务端反过来调用客户端函数,这就看起来有点让人感到迷惑了。

       其实Receiver更简单,所有Broadcast都是从 ActivityManagerService发出的,所以只需要让 ActivityManagerService知道你的Receiver就行了,这是通过 ActivityManagerNative.registerReceiver完成的。实现自己的Receiver时都是实现 BroadcastReceiver接口,BroadcastReceiver本身并不是可以跨进程调用的,这是由 ActivityThread.PackageInfo.ReceiverDispatcher来包装的。

       这里值得注意的是Receiver都是在ActivityThread里处理的,而不是在Binder线程里处理的,主要目的可能为了避免不必要的加锁操作吧。

Java代码:
  1. case BINDER_TYPE_FD: {
  2. int target_fd;
  3. struct file *file;

  4. if (reply) {
  5. if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
  6. binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",
  7. proc->pid, thread->pid, fp->handle);
  8. return_error = BR_FAILED_REPLY;
  9. goto err_fd_not_allowed;
  10. }
  11. } else if (!target_node->accept_fds) {
  12. binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",
  13. proc->pid, thread->pid, fp->handle);
  14. return_error = BR_FAILED_REPLY;
  15. goto err_fd_not_allowed;
  16. }

  17. file = fget(fp->handle);
  18. if (file == NULL) {
  19. binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",
  20. proc->pid, thread->pid, fp->handle);
  21. return_error = BR_FAILED_REPLY;
  22. goto err_fget_failed;
  23. }
  24. target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
  25. if (target_fd < 0) {
  26. fput(file);
  27. return_error = BR_FAILED_REPLY;
  28. goto err_get_unused_fd_failed;
  29. }
  30. task_fd_install(target_proc, target_fd, file);
  31. binder_debug(BINDER_DEBUG_TRANSACTION,
  32. " fd %ld -> %d\n", fp->handle, target_fd);
  33. /* TODO: fput? */
  34. fp->handle = target_fd;
  35. } break;
复制代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值