在W.Richard.Stevens的《UNIX 网络编程 卷二:进程间通信》一书中,对常见的三种IPC(消息队列、信号量、共享内存)分别讲解了posix和system V标准的解决方案。对于这两种标准,起初的目的都是为了解决IPC的问题而形成的一种协议和规范,它们都给出了各自的IPC类型所必须满足的特性和相关的命名规范,这是无关于任何具体系统实现的。posix相对于system V可以说是比较新的标准,语法相对简单。
UNIX两大贡献者贝尔实验室和BSD,在进程之间通信侧重不同,前者基于内核对进程之间的通信手段进行了改进,形成了“System V IPC”,而后者则是基于网络形成了套接字。 而POSIX则是IEEE制定的标准,目的是为运行在不同操作系统上的软件提供统一的接口,实现者则是不同的操作系统内核开发人员。在信号量这种常用的同步互斥手段方面,POSIX在无竞争条件下是不会陷入内核的,而SYSTEM V则是无论何时都要陷入内核,因此性能稍差。 POSIX的sem_wait函数成功获取信号量后,进程如果意外终止,将无法释放信号量,而System V则提供了SEM_UNDO选项来解决这个问题。因此,相比而言,后者更加可靠。 可能有小部分操作系统没有实现POSIX标准,System V更加广泛些,但是考虑到可移植性POSIX必然是一个趋势。在IPC,进程间的消息传递和同步上,似乎POSIX用得较普遍,而在共享内存方面,POSIX实现尚未完善,system V仍为主流。
在两种IPC方面的使用选择:
在观察使用进程间通信手段后,会发现在多线程中使用的基本是POSIX标准提供的接口函数,而多进程则是基于System V。但是两者难道就不能交叉使用吗?
system V是早期实践中弄出来的,posix是后来标准化之后的产物。这个导致了posix的接口设计更加严谨完善,但特殊情况下处理消息不及system V灵活posix ipc的那套接口做到了线程安全,system V的就不见得了,如果你只考虑在linux上开发,就选posix那套就行了,还能和select/poll这些好东西一起用如果还要考虑其他平台的兼容性,那就具体情况具体分析了,有些平台上有些库对posix实现的完整程度还不如system V。
对于三种类型的posix IPC——消息队列、信号量、共享内存——都是用路径名标识的。但是这些路径名既可以是文件系统中的实际路径名,也可以不是,这点不一致性会导致一个移植性的问题。
对于system V IPC的多数实现有内在的内核限制,列入消息队列的最大数目、每个信号量集的最大信号量数,等等。不幸的是,这些大小被内核限制的往往很小,这是因为其中很多限制起源于在某个小地址空间系统上完成的最初实现。然而万幸的是多数系统允许管理员部分或完全修改这些默认限制,但是不同分隔的Unix所需的步揍也不一样。多数系统要求在修改完值后重启内核。尽管如此,某些实现任然给其中一些限制使用16位整数,这在无形之中提供了一个难以突破的硬限制。