Android中使用Binder进行IPC的优点
在 Android 堆栈中使用 Binder 进行 IPC(信号量、消息队列、PIPES)有什么优势?
What is the advantage of using Binder for IPC over (Semaphores , Message Queue, PIPES) in Android stack?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
老问题(可能不受发帖人监控),但值得回答:
A)所有基于文件系统或文件系统可表示的 IPC 机制(特别是管道)都无法使用,因为缺少世界可写目录,其中所有进程可以 mkfifo/创建其 IPC 端口的文件系统/套接字表示(尽管 /dev/socket,它用于系统进程,例如 rile、zygote 及其同类)。
B) 所建议的机制均不具备 Android 所需的“服务定位”能力。在 UNIX 中,有一个 RPC 端口映射器,Android 也需要类似的功能。输入:ServiceManager,它可以使用绑定器注册为上下文管理器,动态注册/查找服务句柄
C) 存在对序列化的广泛需求 - 无论是意图还是其他消息。 Binder 提供了 Parcel 抽象,可用于 Parcel.java 进行数据编组。
D) SysV 还有比 Lambada 先生的回答更重要的其他问题,特别是竞争条件和缺乏授权。
E) 消息队列和管道不能传递描述符。 UNIX 域套接字可以,但不能使用,因为 (A)(再次强调,除非你是 root/系统,如 zygote、rild、installd..)
F) Binder 确实是轻量级的,并且具有内置的授权机制。它还具有一些很棒的功能,例如唤醒接收进程以及内存共享,这是其他机制所不具备的。 (请记住,没有 mmap(2),因为 (A) 中的命名映射存在文件问题)。
而且 - 我们不要忘记
G) Binder 是在 Palm 上启动的(啊,怀旧)(qv OpenBinder)。前 Palmers 进入 Android,并带来了他们的代码。
Old question (and likely unmonitored by the poster), but worth answering:
A) All filesystem-based or filesystem-representable IPC mechanisms (notably pipes), can't be used because of a lack of a world-writable directory, where all processes can mkfifo/create the filesystem/socket representation of their IPC port (/dev/socket notwithstanding, which is used for system processes, e.g. rile, zygote, and their ilk).
B) None of the suggested mechanisms have the capability of "service location" which is required for Android. In UNIX, there's an RPC portmapper, and Android needs similar functionality. Enter: The ServiceManager, which can use binder to register as a context manager, to register/lookup service handles on the fly
C) There is an extensive need for serialization - be it intents, or other messages. Binder provides the parcel abstraction, which can be used for data marshaling by the Parcel.java.
D) SysV has other issues than Mr. Lambada's answer which are more paramount, notably race conditions, and lack of authorization.
E) Message queues and pipes can't pass descriptors. UNIX Domain sockets may, but can't be used because of (A) (again, unless you're root/system, like zygote, rild, installd..)
F) Binder is really lightweight, and has built-in authorization mechanisms. It also has nifty features like waking up the recipient process, as well as memory sharing, which the other mechanisms simply don't have. (and remember, no mmap(2), because of the file problem in (A) for named mappings).
and - let's not forget
G) Binder was started at Palm (ah, nostalgia) (q.v. OpenBinder). Ex-palmers got to Android, and brought their code in with them.
来自 ndk 的 docs/system/libc/SYSV-IPC.html< /a> 文件:
Android 不支持 System V IPC,即以下标准 Posix 标头提供的设施:
其原因是,从设计上来说,它们会导致全局内核资源泄漏。
例如,在以下情况下,无法自动释放内核中分配的 SysV 信号量:
自动终止进程为新进程腾出空间是 Android 应用程序生命周期实现的重要组成部分。这意味着
即使假设只有无错误和无恶意的代码,随着时间的推移,用于实现 SysV IPC 的内核全局表也很可能会被填满
向上。
那时,可能会发生奇怪的故障,并阻止使用它们的程序正常运行,直到系统下次重新启动。
From the ndk's docs/system/libc/SYSV-IPC.html file:
Android does not support System V IPCs, i.e. the facilities provided by the following standard Posix headers:
The reason for this is due to the fact that, by design, they lead to global kernel resource leakage.
For example, there is no way to automatically release a SysV semaphore allocated in the kernel when:
Killing processes automatically to make room for new ones is an important part of Android's application lifecycle implementation. This means
that, even assuming only non-buggy and non-malicious code, it is very likely that over time, the kernel global tables used to implement SysV IPCs will fill
up.
At that point, strange failures are likely to occur and prevent programs that use them to run properly until the next reboot of the system.
绑定器用于跨进程边界进行通信,因为不同的进程不共享公共 VM 上下文 =>不再直接访问彼此的对象(内存)。同一进程中的双方(通常是同一应用程序中的事物)意味着(恕我直言)您不应该使用活页夹,因为它们会减慢/复杂化不必要的事情。
绑定器通常不直接使用,而是通过“Service”或“Messenger”类使用。虽然与服务的通信是通过完整的 api 函数完成的,但与 Messenger 的通信必须使用“消息”。 Messenger 的实现要简单得多。
除了使用 Binder 之外,您还可以使用任何 VM 实例中可用的任何内容,例如“LocalSocket”、文件、ContentProvider、Intents...
Binder 并不适合传输大型数据流(例如音频/视频),因为每个对象都必须转换为(或从)包裹转换回来。所有的转换都需要时间。在这种情况下,例如 LocalSocket 会更好。
Binders are used to to communicate over process boundaries since different processes don't share a common VM context => no more direct access to each others Objects (memory). Both parties within the same process (usually things that are within the same app) means (imho) that you should not use Binders since they slow down / complexify things unnecessary.
Binders are usually not used directly but rather via the "Service" or the "Messenger" classes. While communication with a Service is done via a full api of functions, the communication with a Messenger has to use "Message"s. Messengers a lot simpler to implement.
Apart from using Binders you can use anything that is available from any VM instance like "LocalSocket"s, Files, ContentProviders, Intents, ...
Binders are not ideal for transferring large data streams (like audio/video) since every object has to be converted to (and back from) a Parcel. All the conversion takes time. Much better in that case would be a LocalSocket for example.
绑定器用于启用远程过程调用。您可以使用您提到的同步工具来实现 RPC,但您还需要编写大量代码才能将其组合在一起......使用 Binder(通常仅在 Android 服务中使用),您需要编写的代码要少得多;仅仅比您实际的远程功能多一点。
Binders are used to enable remote procedure calls. You could implement RPC using the synchronization tools you mention but you would also need to write a lot of code to make it come together... with a Binder (normally only used within an Android Service) you have much less code to write; barely more than your actual remote functions.