进程间通信这块是学习linux-c编程的关键, 这篇为后续进程间通信技术的引子篇,后续讲到单独的某一个系统调用 都附该引用。
IPC是进程间通信(interprocess communication)的简称。系统上不同进程之间消息传递(message passing)的方式。
共享内存需要某种实行的同步(synchronization)参与运作。
发展阶段。
管道
(pipe) 是第一个广泛使用的IPC形式, 使用在Kernel之上的(应用程序或shell)。
System V消息队列
(System V message queue)
有亲缘关系
不仅指父子,还包含子子关系,比如fork两次,派生2个子进程。
所有Unix进程与init进程都有亲缘关系。
Posix消息队列
远程过程调用
(Remote Procedure Call, RPC)
同步演变
记录上锁
(record locking) 1988年由Posix.1标准化。System V信号量
(System V semaphore)是System V消息队列加上System V内核的同事伴随System V共享内存(System V shared memory)加入的。Posix信号量
(Posix semaphore)和Posix共享内存也由Posix实时标准加入。互斥锁(mutex)和条件变量
(condition variable)是由Posix线程标准定义的两种同步形式。尽管往往用于线程间的同步,他们也能提供不同进程间的同步。读写锁
(read-write lock)是另一种形式的同步。按照传统的Unix编程模型,我们在一个系统上运行多个进程,每个进程都有各自的地址空间。Unix进程间的信息共享可以有多个方式:
1)左边的两个进程共享存留于文件系统中某个文件上的某些信息。为访问这些信息,每个进程都得穿越内核(例如read,write, lseek等)。当一个文件有待更新时,某种形式的同步是必要的,这样即可保护多个写入者,防止相互干扰,也可保护一个或多个读出者,防止写入者的干扰。
2)中间的两个进程共享驻留于内核中的某些信息。管道是这种共享类型的一个例子,System V消息队列和System V 信号量也是。现在访问共享信息的每次操作涉及对内核的一次系统调用。
3)右边的两个进程有一个双方都能访问的共享内存区。每个进程一旦设置好该共享内存区,就能根本不涉及内核而访问其中的数据。共享该内存区的进程需要某种形式的同步。
注意没有任何东西限制任何IPC技术只能使用两个进程。我们讲述的技术适用于任意数目的进程。
线程
虽然Unix系统中进程的概念已使用很久,一个给定进程中多个线程(thread)的概念却相对较新。Posix.1线程标准 (称Pthreads)是于1995年通过的。从IPC角度看来,一个给定进程内的所有线程共享同样的全局变量。
然而我们必须关注的是各个线程间对全局数据的同步访问。同步尽管不是一种明确的IPC形式,但它确实伴随许多形式的IPC使用, 以控制对某些共享数据的访问。
我们可以把任意类型的IPC的持续性(persistence)定义成该类型的一个对象一直存在多长时间。以下展示了三种类型的持续性。
IPC类型 | 持续性 |
---|---|
管道 | 随进程 |
FIFO | 随进程 |
Posix互斥锁 | 随进程 |
Posix条件变量 | 随进程 |
Posix读写锁 | 随进程 |
fcntl记录锁 | 随进程 |
Posix消息队列 | 随内核 |
Posix有名信号量 | 随内核 |
Posix基于内存的信号量 | 随进程 |
Posix共享内存区 | 随内核 |
System V消息队列 | 随内核 |
System V信号量 | 随内核 |
System V共享内存区 | 随内核 |
TCP套接字 | 随进程 |
UDP套接字 | 随进程 |
Unix域套接字 | 随进程 |
注意该列表中没有任何类型的IPC具备随文件系统的持续性,但是我们说过有三种类型的Posix IPC可能会具备该持续性, 这取决于它们的实现。显然,向一个文件写入数据提供了随文件系统的持续性,但这通常不作为一种IPC形式使用。多数形式的IPC并没有在系统重新自举后继续存在的打算,因为进程不可能跨越重新自举继续存活。对于一种给定形式的IPC,要求它具备随文件系统的持续性可能会将其性能降低,而IPC的一个基本的设计目标是高新能。
IPC类型 | 用于打开或创建IPC的名字空间 | IPC打开后的标识 | Posix.1 1996 | Unix98 |
---|---|---|---|---|
管道 | 没有名字 | 描述符 | * | * |
FIFO | 路径名 | 描述符 | * | * |
Posix互斥量 | 没有名字 | pthread_mutex_t指针 | * | * |
Posix条件变量 | 没有名字 | pthread_cond_t指针 | * | * |
Posix读写锁 | 没有名字 | pthread_rwlock_t指针 | * | |
fcntl记录上锁 | 路径名 | 描述符 | * | * |
Posix消息队列 | Posix IPC名字 | mqd_t值 | * | * |
Posix有名信号量 | Posix IPC名字 | sem_t指针 | * | * |
Posix基于内存的信号量 | 没有名字 | sem_t指针 | * | * |
Posix共享内存区 | Posix IPC名字 | 描述符 | * | * |
System V消息队列 | key_t键 | System V IPC标识符 | * | |
System V 信号量 | key_t键 | System V IPC标识符 | * | |
System V共享内存区 | key_t键 | System V IPC标识符 | * | |
门 | 路径名 | 描述符 | ||
Sun RPC | 程序/版本 | RPC句柄 | ||
TCP套接字 | IP地址与端口 | 描述符 | .1g | * |
UDP套接字 | ip和端口 | 描述符 | .1g | * |
Unix域套接字 | 路径名 | 描述符 | .1g | * |
尽管Posix.1标准化了信号量,他们依然是可选的。