常见的进程间通信方法
常见的进程间通信方法有:
管道(Pipe)
消息队列
共享内存
信号量
套接字
下面,我们将详细介绍共享内存的原理以及具体实现。
什么是共享内存?
Windows共享内存(Shared Memory in Windows)是一种操作系统机制,允许不同的进程(程序)共享一段内存空间。这意味着多个进程可以同时访问同一个内存区域,用以交换数据或进行通信,这是进程间通信(IPC)的一种形式。使用共享内存通常可以提高应用程序之间的数据交换效率,因为它避免了数据的复制过程,直接在内存中进行读写。
共享内存的实现方式
在Windows系统中,共享内存的实现通常有以下几种方式:
内存映射文件:
这是最常见的实现共享内存的方式。通过将磁盘上的文件映射到内存地址空间,文件的内容可以被映射到多个进程的地址空间,从而实现共享。
命名管道:
虽然主要用于进程间的消息传递,命名管道也可以配置为在内存中传输数据,从而模拟共享内存的效果。
剪贴板:
剪贴板提供了一种将数据存储在共享内存中的方法,这样不同的程序可以访问和修改这些数据。
全局原子表:
全局原子表允许程序创建小段的、全局可访问的数据(原子),这些数据可由其他程序读取和修改。
本文只介绍内存映射文件这种方式。
内存映射文件原理
文件与内存的映射
内存映射文件通过将磁盘上的文件或一段虚拟内存与进程的地址空间进行映射来工作。这种映射实际上是创建了文件内容与进程虚拟地址空间之间的直接联系。
操作系统的角色
操作系统负责管理内存和磁盘文件之间的映射关系。当一个文件被映射到内存时,操作系统将文件的一部分或全部内容呈现为进程虚拟内存的一部分。这样,对这部分虚拟内存的访问就相当于直接读写文件内容。
虚拟内存管理
分页机制
操作系统使用分页机制来管理物理内存和虚拟内存。内存映射文件利用这一机制,将文件的内容按页对应到虚拟内存页上。
当进程访问这些虚拟页时,如果对应的物理页不在内存中(即页面错误),操作系统将从磁盘中加载所需的数据页到物理内存中。
写时复制(Copy-on-Write)
对于共享内存映射,操作系统可能使用写时复制策略。这意味着当进程试图写入共享内存时,系统会为该进程创建这部分内存的私有副本,从而保护原始内存内容。
延迟加载
内存映射文件通常不会在映射时立即加载整个文件内容。而是采用延迟加载的方式,即只有在实际访问某个内存区域时,相应的文件部分才被加载到物理内存中。这样可以提高效率,减少内存消耗。
同步和一致性
操作系统还负责同步映射文件的内存视图和磁盘上的文件内容。当进程修改了映射的内存后,这些变更可能会延迟写回到磁盘文件中。这涉及到内存和磁盘操作的一致性和同步问题。
性能优势
内存映射文件提供了比传统的文件I/O更快的数据访问速度,因为它避免了多次的数据复制和用户空间与内核空间之间的上下文切换。数据直接在内存中修改,只在必要时进行磁盘I/O操作。
接口介绍
CreateFileMappint
功能
基于实际的磁盘文件或系统分页文件来创建内存映射文件对象。
声明
HANDLE CreateFileMapping(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCTSTR lpName
);
参数
hFile:文件句柄,INVALID_HANDLE_VALUE用于系统分页文件。
lpAttributes:安全属性,通常为NULL
flProtect:保护属性,读写权限
PAGE_READONLY:分配的页面只读
PAGE_READWRITE:分配的页面可读可写
PAGE_WRITECOPY:分配的页面写时复制,就是当多个进程映射到同一个内存区域进行读写操作时,它们实际上是在读取同一份数据的副本。但是,当任何一个进程尝试修改这些数据时,操作系统会为该进程创建这部分数据的私有副本,从而隔离修改操作,确保其他进程看到的数据仍然是未被修改的原始数据
PAGE_EXECUTE:分配的页面可执行,不可写入。这通常用于执行代码,而非存储数据
PAGE_EXECUTE_READ:分配的页面可执行和可读。这适用于执行某些代码,同时需要从相同的内存区域读取数据
PAGE_EXECUTE_READWRITE:分配的页面可执行、可读写。这是最灵活的权限,允许执行代码并修改数据
PAGE_EXECUTE_WRITECOPY:分配的页面可执行、可读、且写时复制。对这些页面的写入不会影响到原始数据或其他映射的视图
dwMaximumSizeHigh: 映射对象的最大大小(高32位)
dwMaximumSizeLow: 映射对象的最大大小(低32位)
lpName: 映射对象的名称,可用于进程间共享
OpenFileMapping
功能
用于打开一个已经存在的内存映射文件对象,通常在不同的进程中使用,以访问由CreateFileMapping创建的共享内存区域。
声明
HANDLE OpenFileMapping(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
参数
dwDesiredAccess:访问文件映射的权限,需要和