本节书摘来自异步社区《unix网络编程 卷2:进程间通信(第2版)》一书中的第1章,第1.1节,作者:【美】w. richard stevens著,更多章节内容可以访问云栖社区“异步社区”公众号查看
ipc是进程间通信(interprocess communication)的简称。传统上该术语描述的是运行在某个操作系统之上的不同进程间各种消息传递(message passing)的方式。本书还讲述多种形式的同步(synchronization),因为像共享内存区这样的较新式的通信需要某种形式的同步参与运作。
在unix操作系统过去30年的演变史中,消息传递历经了如下几个发展阶段。
管道(pipe,第4章)是第一个广泛使用的ipc形式,既可在程序中使用,也可从shell中使用。管道的问题在于它们只能在具有共同祖先(指父子进程关系)的进程间使用,不过该问题已随有名管道(named pipe)即fifo(第4章)的引入而解决了。
system v消息队列(system v message queue,第6章)是在20世纪80年代早期加到system v内核中的。它们可用在同一主机上有亲缘关系或无亲缘关系的进程之间。尽管称呼它们时仍冠以“system v”前缀,当今多数版本的unix却不论自己是否源自system v都支持它们。
在谈论unix进程时,有亲缘关系(related)的说法意味着所论及的进程具有某个共同的祖先。说得更明白点,这些有亲缘关系的进程是从该祖先进程经过一次或多次fork派生来的。一个常见的例子是在某个进程调用fork两次,派生出两个子进程。我们说这两个子进程是有亲缘关系的。同样,每个子进程与其父进程也是有亲缘关系的。考虑到ipc,父进程可以在调用fork前建立某种形式的ipc(例如管道或消息队列),因为它知道随后派生的两个子进程将穿越fork继承该ipc对象。我们随图1-6详细讨论各种ipc对象的继承性。我们还得注意,从理论上说,所有unix进程与init进程都有亲缘关系,它是在系统自举时启动所有初始化进程的祖先进程。然而从实践上说,进程亲缘关系开始于一个登录shell(称为一个会话)以及由该shell派生的所有进程。apue的第9章详细讨论会话和进程亲缘关系。 本书将全文使用缩进的插入式注解(如此处所示)来说明实现上的细节、历史上的观点以及其他琐事。
posix消息队列(posix消息队列,第5章)是由posix实时标准(1003.1b-1993,将在1.7节详细讨论)加入的。它们可用在同一主机上有亲缘关系和无亲缘关系的进程之间。
远程过程调用(remote procedure call,简称rpc,第5部分)出现在20世纪80年代中期,它是从一个系统(客户主机)上某个程序调用另一个系统(服务器主机)上某个函数的一种方法,是作为显式网络编程的一种替换方法开发的。既然客户和服务器之间通常传递一些信息(被调用函数的参数与返回值),而且rpc可用在同一主机上的客户和服务器之间,因此可认为rpc是另一种形式的消息传递。
看一看由unix提供的各种同步形式的演变同样颇有教益。
需要某种同步形式(往往是为了防止多个进程同时修改同一文件)的早期程序使用了文件系统的诡秘特性,我们将在9.8节讨论其中的一些。
记录上锁(record locking,第9章)是在20世纪80年代早期加到unix内核中的,然后在1988年由posix.1标准化的。
system v信号量(system v semaphore,第11章)是在system v消息队列加入system v内核的同时(20世纪80年代早期)伴随system v共享内存区(system v shared memory)加入的。当今多数版本的unix都支持它们。
posix信号量(posix semaphore,第10章)和posix共享内存区(posix shared memory,第13章)也由posix实时标准(1003.1b-1993)加入。
互斥锁(mutex)和条件变量(condition variable,见第7章)是由posix线程标准(-1995)定义的两种同步形式。尽管往往用于线程间的同步,它们也能提供不同进程间的同步。
读写锁(read-write lock,第8章)是另一种形式的同步。它们还没有被posix标准化,不过也许不久后会被标准化。