为了解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的值可能与原进程不一样。
http://dev.10086.cn/cmdn/wiki/index.php?doc-view-6363.html
1.文件描述符是如何在进程之间传递的?
我们知道文件描述符,就像虚拟内存的地址一样,是进程私有的资源。在一个进程中文件描 述符,在另外一个进程中,可能是无效的,也可能是对应另外一个文件。Android却可以把文件描述符从一个进程传到另外一个进程。第一次发现这种情况时,让我感到很惊奇,所以花了点时间去研究。看明白之后,发现其实现也 很简单:
Java代码:
在对文件描述符打包时,把对象的类型设置为BINDER_TYPE_FD。
在binder的内核模块binder_transaction函数中,我们可以看:
Java代码:
这里如果是文件描述符,就在目标进程中重新打开同一个文件了(虽然打开的是同一个文件,但目标进程拿到的文件描述符可能不相同)。
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:
http://blog.csdn.net/black_berry/article/details/6618307
http://blog.csdn.net/black_berry/article/details/6621297
http://blog.csdn.net/black_berry/article/details/6621318
http://blog.csdn.net/black_berry/article/details/6621327
http://blog.csdn.net/black_berry/article/details/6621391
http://blog.csdn.net/black_berry/article/details/6621411
http://blog.csdn.net/black_berry/article/details/6621435
http://www.21876.com/project/Android/71246.html
http://blog.csdn.net/t80t90s/article/details/7704375
http://hi.baidu.com/woodyqt/item/3a5362d97982613b48e1ddab
http://www.redwolf-blog.com/?p=902
http://blog.csdn.net/lihui130135/article/details/7372282
http://w.hudong.com/3fdeadabfa514f1faf372c589632f692.html
http://www.blogjava.net/mixer-a/archive/2012/04/17/374989.html
这个人的blog也不错