博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android binder相关
阅读量:2171 次
发布时间:2019-05-01

本文共 2414 字,大约阅读时间需要 8 分钟。

为了解android如何在不同进程间传递fd,搜索了一下资料。

在binder内核代码中,对BINDER_TYPE_FD,会先

fget(fp->handle);

然后:

target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);

task_fd_install(target_proc, target_fd, file);

这样就相当于在新的进程理重新打开该文件,但得到的fd的值可能与原进程不一样。

 

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

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

  1. 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);
    9. }

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

  1. 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线程里处理的,主要目的可能为了避免不必要的加锁操作吧。

 

 

搜索了几篇blog:

 

 

 

 

 

 

 

这个人的blog也不错

转载地址:http://hpqzb.baihongyu.com/

你可能感兴趣的文章
博客文格式优化
查看>>
【托业】【新托业全真模拟】疑难语法题知识点总结(01~05)
查看>>
【SQL】group by 和order by 的区别。
查看>>
【Python】详解Python多线程Selenium跨浏览器测试
查看>>
Jmeter之参数化
查看>>
Shell 和Python的区别。
查看>>
Python 列表(list)、字典(dict)、字符串(string)常用基本操作小结
查看>>
Loadrunner之https协议录制回放报错如何解决?(九)
查看>>
python中xrange和range的异同
查看>>
列表、元组、集合、字典
查看>>
【Python】easygui小甲鱼
查看>>
【Python】关于Python多线程的一篇文章转载
查看>>
【Pyton】【小甲鱼】文件
查看>>
【Pyton】【小甲鱼】永久存储:腌制一缸美味的泡菜
查看>>
【Pyton】【小甲鱼】异常处理:你不可能总是对的
查看>>
APP性能测试工具
查看>>
【Pyton】【小甲鱼】类和对象
查看>>
压力测试工具JMeter入门教程
查看>>
作为一名软件测试工程师,需要具备哪些能力
查看>>
【Pyton】【小甲鱼】类和对象:一些相关的BIF(内置函数)
查看>>