在 Android 堆栈中使用 Binder for IPC 优于(信号量、消息队列、PIPES)有什么优势?
4 回答
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文件中:
Android 不支持 System V IPC,即以下标准 Posix 标头提供的设施:
<sys/sem.h> /* SysV semaphores */
<sys/shm.h> /* SysV shared memory segments */
<sys/msg.h> /* SysV message queues */
<sys/ipc.h> /* General IPC definitions */
其原因是,根据设计,它们会导致全局内核资源泄漏。
例如,在以下情况下,无法自动释放内核中分配的 SysV 信号量:
- 错误或恶意进程退出
- 一个非错误且非恶意的进程崩溃或被明确杀死。
自动终止进程以为新进程腾出空间是 Android 应用程序生命周期实现的重要组成部分。这意味着,即使只假设没有错误和无恶意代码,随着时间的推移,用于实现 SysV IPC 的内核全局表很可能会填满。
此时,可能会发生奇怪的故障并阻止使用它们的程序正常运行,直到系统下次重新启动。
绑定器用于通过进程边界进行通信,因为不同的进程不共享公共 VM 上下文 => 不再直接访问彼此的对象(内存)。同一进程中的双方(通常是同一应用程序中的事物)意味着(恕我直言)您不应该使用 Binder,因为它们会减慢/复杂化不必要的事情。
活页夹通常不直接使用,而是通过“服务”或“信使”类使用。虽然与服务的通信是通过完整的函数 API 完成的,但与 Messenger 的通信必须使用“消息”。Messenger 实现起来要简单得多。
除了使用 Binder,您还可以使用任何 VM 实例中可用的任何内容,例如“LocalSocket”、文件、ContentProviders、Intents……
绑定器对于传输大型数据流(如音频/视频)并不理想,因为每个对象都必须转换为(和返回)一个 Parcel。所有的转换都需要时间。在这种情况下,例如 LocalSocket 会更好。
绑定器用于启用远程过程调用。您可以使用您提到的同步工具来实现 RPC,但您还需要编写大量代码以使其结合在一起......使用 Binder(通常仅在 Android 服务中使用),您编写的代码要少得多;仅比您实际的远程功能多一点。