IPC是进程间通信的简称。
进程、线程与信息共享
Unix进程间的信息共享的方式:
(1) 左边的两个进程共享存留于文件系统中某个文件上的某些信息。为访问这些信息、每个进程都得穿越内核(例如read、write、lseek等)。当一个文件有待更新时,某种形式的同步是必要的,这样既可保护多个写入者,防止相互串扰,也可保护一个或多个读出者,防止写入者的干扰。
(2)中间的两个进程共享驻留于内核中的某些信息。是这种共享类型的一个例子,System V消息队列和System V信号量也是。现在访问共享信息的每次操作涉及对内核的一次系统调用
(3)右边的两个进程有一个双方都能访问的共享内存区。每个进程一旦设置好该共享内存区,就能根本不涉及内核而访问其中的数据。共享该内存区的进程需要某种形式的同步。
IPC对象的持续性
(1)随进程持续的( process-persistent)IPC对象一直存在到打开着该对象的最后一个进程关闭该对象为止。例如管道和FIFO就是这种对象。
(2)随内核持续的(kernel-persistent)IPC对象一直存在到内核重新自举或显式删除该对象为止。例如System V的消息队列、信号量和共享内存区就是此类对象。Posix的消息队列、信号量和共享内存区必须至少是随内核持续的,但也可以是随文件系统持续的,具体取决于实现。
(3)随文件系统持续的( filesystem-persistent)IPC对象一直存在到显式删除该对象为止。即使内核重新自举了,该对象还是保持其值。Posix消息队列、信号量和共享内存区如果是使用映射文件实现的(不是必需条件),那么它们就是随文件系统持续的。但是这种情况很少见,不可能说已经重新自举了内核,却还有老进程活着的情况。
名字空间
fork、exec、和exit对IPC对象的影响
Posix IPC
- Posix消息队列
- Posix信号量
- Posix共享内存区
PosixIPC函数汇总:
posix标准,独爱下划线。
创建与打开IPC通道
mg_open、sem_open和shm_open这三个创建或打开一个IPC对象的函数,它们的名为oflag的第二个参数指定怎样打开所请求的对象。
oflag:
前3行指定怎样打开对象:只读、只写或读写。消息队列能以其中任何一种模式打开,信号量的打开不指定任何模式(任意信号量操作,都需要读写访问权),共享内存区对象则不能以只写模式打开。
余下的4个标志是可选的:
O_EXCL:
如果该标志和O_CREAT一起指定,那么IPC函数只在所指定名字的消息队列、信号量或共享内存区对象不存在时才创建新的对象,如果该对象已经存在,而且指定了o_CREAT |O_EXCL,那么返回一个EEXIST错误。检查存在和创建这两步一定是原子的。
O_NONBLOCK:
该标志使得一个消息队列在队列为空时实或队列填满时的写不被阻塞。
O_TRUNC:
如果以读写模式打开了一个已存在的共享内存区对象,那么该标志将使得该对象的长度被截成0。
O_CREAT:
若不存在,则创建,创建时需要指定mode参数(指定权限):
这些常值定义在<sys/stat.h>头文件中。所指定的权限位受当前进程的文件模式创建掩码(file mode creation mask)修正,而该掩码可通过调用umask函数(APUE第83~85页)或使用shell的umask命令来设置。
跟新创建的文件一样,当创建一个新的消息队列、信号量或共享内存区对象时,其用户ID被置为当前进程的有效用户ID。信号量或共享内存区对象的组ID被置为当前进程的有效组ID或某个系统默认组ID。新消息队列对象的组ID则被置为当前进程的有效组ID。
打开一个IPC对象的真正逻辑流程:
IPC权限
权限的讲解不用太复杂,你以某一种权限创建出来一个IPC,它就是一个文件描述符,既然是文件,就有读写权限,和Linux文件系统一样。
System V IPC
- System V 消息队列
- System V 信号量
- System V 共享内存区
key_t键和ftok函数
三种类型的System V IPC使用key_t值作为它们的名字。头文件<sys/types.h>把key_t这个数据类型定义为一个整数,它通常是一个至少32位的整数。这些整数值通常是由ftok函数赋予的。
函数ftok把一个已存在的路径名和一个整数标识符转换成一个key_t值,称为IPC键。
该函数假定对于使用System V IPC的某个给定应用来说,客户和服务器同意使用对该应用有一定意义的pathname。它可以是服务器守护程序的路径名、服务器使用的某个公共数据文件的路径名或者系统上的某个其他路径名。如果客户和服务器之间只需单个IPC通道,那么可以使用譬如说值为1的id。如果需要多个IPC通道,譬如说从客户到服务器一个通道,从服务器到客户又一个通道,那么作为一个例子,一个通道可使用值为l的id,另一个通道可使用值为2的id。客户和服务器一旦在pathname和id上达成一致,双方就都能调用ftok函数把pathname和id转换成同一个IPC键。
ipc_perm结构
创建和打开IPC通道
创建或打开一个IPC对象的三个XXXget函数的第一个参数key是类型为key_t的IPC键,返回值identifier是一个整数标识符。该标识符不同于ftok函数的id参数,我们不久就会看到。对于key值,应用程序有两种选择。
(1)调用ftok,给它传递pathname和id。
(2)指定key为IPC_PRIVATE,这将保证会创建一个新的、唯一的IPC对象。
ipcs和ipcrm程序
使用 ipcs 命令可以查看已经存在的ipc,使用ipcrm 杀掉不用的ipc。
由于System V IPC的三种类型不是以文件系统中的路径名标识的,因此使用标准的1s和rm程序无法看到它们,也无法删除它们。不过实现了这些类型IPC的任何系统都提供两个特殊的程序: ipcs和ipcrm。 ipcs输出有关System V IPC特性的各种信息,ipcrm则删除一个System V消息队列、信号量集或共享内存区。前者支持十来个命令行选项,它们决定报告哪种类型的IPC以及输出哪些信息,后者支持6个命令行选项。所有这些选项的详细信息可查阅它们的手册页面。
不喜欢使用System V标准的IPC,不好用,而且大部分限制还要修改内核。