三. 一些基本解释
进程和线程 进程间共享信息 进程间机制持久化 进程间机制命名 进程间具名资源的构造、析构及生命周期 许可 |
进程和线程
Boost.Interprocess不仅仅能在进程间工作,也能在线程间工作。Boost.Interprocess的同步机制能同步不同进程间的线程以及同一进程内的线程。
进程间共享信息
在传统编程模式中,一个操作系统有多个进程在运行,每个进程都有自己独立的地址空间。为了在进程间共享信息,我们有以下几个选择:
- 两个进程使用文件共享信息。为了获得数据,每个进程使用通常的文件读/取机制。当更新/读取一个多进程共享的文件时,我们需要一些同步机制来保护读取和写入。
- 两个进程共享驻留在操作系统内核的信息。例如,传统的消息队列。同步机制由操作系统的内核来维护。
- 两个进程共享一个内存区域。这就是通常的共享内存或内存映射文件。一旦某进程建立了内存区域,则进程们可以像使用其他内存片段一样读/写数据,而不需要调用操作系统内核。这种方式也需要人工进行进程间的同步处理。
进程间机制持久化
进程间通信机制的一个最大问题在于进程间通信机制的生命周期。了解进程间通信机制何时在系统中消失是很关键的。在Boost.Interprocess中,我们有3种持久化措施:
- 进程持久化:机制一直保留,直到所有打开机制的进程关闭、退出或崩溃。
- 内核持久化:机制一直存在,直到操作系统内核重启或是机制被显式删除。
- 文件系统持久化:机制一直存在直到被显式删除。
一些本地(native)的POSIX和Windows IPC机制有不同的持久化方式,因此在Windows和POSIX本地机制间达到兼容是非常困难的。
Boost.Interprocess类族有以下持久化方式:
表 12.1. Boost.Interprocess 持久化表格
机制 | 持久化 |
共享内存 | 内核或文件系统 |
内存映射文件 | 文件系统 |
进程共享互斥类型 | 进程 |
进程共享信号量 | 进程 |
进程共享条件变量 | 进程 |
文件锁 | 进程 |
消息队列 | 内核或文件系统 |
具名互斥量 | 内核或文件系统 |
具名信号量 | 内核或文件系统 |
具名条件变量 | 内核或文件系统 |
如上所示,Boost.Interprocess定义了一些机制采用的是“内核或文件系统”方式持久化。这是因为POSIX具有允许本地进程间通信实现的可能性。例如,可以使用内存映射文件执行共享内存并且获得文件系统持久化(例如,目前没有适当的方式使用采用本地共享内存的Windows共享内存用户库来模拟内核持久化,或为了POSIX共享内存的进程持久化,因此唯一可移植的方式是定义“内核或文件系统”持久化。)
进程间机制命名
一些进程间机制是在共享内存或内存映射文件中创建的匿名对象,但另外一些进程间机制需要一个名字或定义,以便两个不相关的进程能使用相同的进程间机制对象。这方面的例子有共享内存、具名互斥量和具名信号量(例如,Windows特有的CreateMutex/CreateSemaphore API 家族)。
用于表示一个进程间机制的名称是不可移植的,甚至在UNIX系统间也不行。基于此原因,Boost.Interprocess将名称限制在了C++变量标识符或关键字:
以大写或小写字母开头,比如a-z或A-Z的字母。例子:Sharedmemory, sharedmemory, sHaReDmEmOrY等等。
可以包含字母、下划线或数字。例子:shm1, shm2and3, ShM3plus4等等。
进程间具名资源的构造、析构及生命周期
具名的Boost.Interprocess资源(共享内存、内存映射文件、具名互斥量/条件变量/信号量)具有内核或文件系统持久化性。这意味着,即使打开这些资源的所有进程都结束了,这些资源还可以被再次打开,并且这些资源仅能显式的通过它们的静态成员删除函数来析构。这一行为很容易理解,因为它与控制文件打开/创建/删除功能使用相同的机制:
表 12.2. Boost.Interprocess与Filesystem类比
具名进程间资源 | 对应的std文件 | 对应的POSIX操作 |
Constructor | std::fstream constructor | open |
Destructor | std::fstream destructor | close |
Member remove | None. std::remove | unlink |
共享内存和具名信号量在POSIX和Boost.Interprocess间的对应关系
表 12.3. Boost.Interprocess和POSIX 共享内存
shared_memory_object 操作 | POSIX 操作 |
Constructor | shm_open |
Destructor | close |
Member remove | shm_unlink |
表12.4. Boost.Interprocess和POSIX 具名信号量
named_semaphore 操作 | POSIX 操作 |
Constructor | sem_open |
Destructor | close |
Member remove | sem_unlink |
最重要的特性是具名资源的析构不会把资源从系统中删除,它们仅释放由操作系统分配的供具名资源进程使用的资源。如果要从系统中删除具名资源,程序员必须使用删除函数。
许可
Boost.Interprocess提供的具名资源依赖于平台相关性许可,当创建文件时也有同样的问题。如果一个程序员想在使用者间共享共享内存、内存映射文件或具名同步机制(互斥量、信号量等等),那就必须明确这些许可。令人沮丧的是,传统的UNIX和Windows许可是非常不同的,并且Boost.Interprocess不尝试统一化这些许可,但不忽视它们。
所有的具名资源构建函数都带一个可选的许可对象,这些许可对象能用平台相关性许可进行配置。
因为每种机制都能被其他不同的机制进行仿真(一个信号量可能被映射文件或本地信号量替代),因此当具名资源的执行方式改变时,许可类型也会不同(例如:Windows互斥量需要同步许可,但这与文件许可类型是不同的)。为避免这点,Boost.Interprocess依赖于类文件许可,需要文件读-写-删许可以便打开具名同步机制(互斥量、信号量等)以及提供给共享内存的合适的读或读-写-删许可。这种方式有两个优点:它类似于UNIX原理,并且程序员不需要了解具名资源是如何执行的。