Android-与Android IPC有关的问题
2011-05-03 15:49
204 查看
1.文件描述符是如何在进程之间传递的?
我们知道文件描述符,就像虚拟内存的地址一样,是进程私有的资源。在一个进程中文件描
述符,在另外一个进程中,可能是无效的,也可能是对应另外一个文件。
Android却可以把文件描述符从一个进程传到另外一个进程。第一次发现这种情况时,让我感到很惊奇,所以花了点时间去研究。看明白之后,发现其实现也
很简单:
在对文件描述符打包时,把对象的类型设置为BINDER_TYPE_FD。
在binder的内核模块binder_transaction函数中,我们可以看:
这里如果是文件描述符,就在目标进程中重新打开同一个文件了(虽然打开的是同一个文件,但目标进程拿到的文件描述符可能不相同)。
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线程里处理的,主要目的可能为了避免不必要的加锁操作吧。
这里通过消息把Receiver的动作执行放到了mActivityThread
线程里。
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静
我们知道文件描述符,就像虚拟内存的地址一样,是进程私有的资源。在一个进程中文件描
述符,在另外一个进程中,可能是无效的,也可能是对应另外一个文件。
Android却可以把文件描述符从一个进程传到另外一个进程。第一次发现这种情况时,让我感到很惊奇,所以花了点时间去研究。看明白之后,发现其实现也
很简单:
1 2 3 4 5 6 7 8 9 | status_t Parcel:: writeFileDescriptor( int fd) { flat_binder_object obj; obj.type = BINDER_TYPE_FD; obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; obj.handle = fd; obj.cookie = ( void * ) 0 ; return writeObject( obj, true ) ; } |
在binder的内核模块binder_transaction函数中,我们可以看:
1 2 3 4 5 6 7 8 910 | case BINDER_TYPE_FD: { int target_fd; struct file * file; if ( reply) { if ( ! ( in_reply_to-> flags & TF_ACCEPT_FDS) ) { binder_user_error( "binder: %d:%d got reply with fd, %ld, but target does not allow fds/n " , proc-> pid, thread-> pid, fp-> handle) ; return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; } } else if ( ! target_node-> accept_fds) { binder_user_error( "binder: %d:%d got transaction with fd, %ld, but target does not allow fds/n " , proc-> pid, thread-> pid, fp-> handle) ; return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; } file = fget( fp-> handle) ; if ( file == NULL ) { binder_user_error( "binder: %d:%d got transaction with invalid fd, %ld/n " , proc-> pid, thread-> pid, fp-> handle) ; return_error = BR_FAILED_REPLY; goto err_fget_failed; } target_fd = task_get_unused_fd_flags( target_proc, O_CLOEXEC) ; if ( target_fd < 0 ) { fput( file) ; return_error = BR_FAILED_REPLY; goto err_get_unused_fd_failed; } task_fd_install( target_proc, target_fd, file) ; binder_debug( BINDER_DEBUG_TRANSACTION, " fd %ld -> %d/n " , fp-> handle, target_fd) ; /* TODO: fput? */ fp-> handle = target_fd; } 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线程里处理的,主要目的可能为了避免不必要的加锁操作吧。
1 2 3 4 5 6 7 8 910 | case BINDER_TYPE_FD: { int target_fd; struct file * file; if ( reply) { if ( ! ( in_reply_to-> flags & TF_ACCEPT_FDS) ) { binder_user_error( "binder: %d:%d got reply with fd, %ld, but target does not allow fds/n " , proc-> pid, thread-> pid, fp-> handle) ; return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; } } else if ( ! target_node-> accept_fds) { binder_user_error( "binder: %d:%d got transaction with fd, %ld, but target does not allow fds/n " , proc-> pid, thread-> pid, fp-> handle) ; return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; } file = fget( fp-> handle) ; if ( file == NULL ) { binder_user_error( "binder: %d:%d got transaction with invalid fd, %ld/n " , proc-> pid, thread-> pid, fp-> handle) ; return_error = BR_FAILED_REPLY; goto err_fget_failed; } target_fd = task_get_unused_fd_flags( target_proc, O_CLOEXEC) ; if ( target_fd < 0 ) { fput( file) ; return_error = BR_FAILED_REPLY; goto err_get_unused_fd_failed; } task_fd_install( target_proc, target_fd, file) ; binder_debug( BINDER_DEBUG_TRANSACTION, " fd %ld -> %d/n " , fp-> handle, target_fd) ; /* TODO: fput? */ fp-> handle = target_fd; } break ; |
线程里。
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静
相关文章推荐
- Android IPC有关的问题
- 两个与Android IPC有关的问题
- Android Please ensure that adb is correctly located at有关问题解决
- Android WebView 文本框获取焦点后自动放大有关问题
- android 弹出软键盘将底部视图顶起有关问题
- 有关android中多级联动问题的解决
- 有关ViewPager的使用及解决Android下ViewPager和PagerAdapter中调用notifyDataSetChanged失效的问题
- 有关android源码编译的几个问题
- 有关获取android唯一识别号IMEI的问题
- 有关ViewPager的使用及解决Android下ViewPager和PagerAdapter中调用notifyDataSetChanged失效的问题
- android怎么获取一个SD卡指定文件夹的图片Uri uri有关问题
- Android 混淆代码有关问题总结
- 有关android内存泄露的问题以及解决方案
- 有关android中多级联动问题的解决
- 关于Android中图片compress的有关问题
- Android 有关View的绘制问题
- Android 编译有关gcc版本的问题
- Android有关自定义标题的问题 You cannot combine custom titles with other title features
- Android中有关布局的几个问题
- 关于Android开发中有关权限的问题