进程之间通讯问题

本文介绍在Windows CE系统中使用映射文件技术实现进程间通信的方法。详细解释了映射文件的创建过程,包括调用CreateFileForMapping创建映射文件、MapViewOfFile映射文件到内存等步骤,并探讨了内存映射文件技术在进程间通信的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

1 映射数据文件

第一步:调用 CreateFileForMapping 函数。在 Windows CE.NET 中推荐使用这个函数替代 CreateFile 函数。 CreateFileForMapping 函数由内核执行并创建文件,它也可以打开由 CreateFile 函数创建的文件。其参数同 CreateFile 相似。参数 1 指定文件路径,注意文件路径的格式是没有盘符的,参数 2 指定访问方式(读 或写),参数 3 指定共享模式,参数 4 指定安全属性(必须设置为 NULL ),参数 5 指定是创建还是打开文件,参数 6 指定文件属性,参数 7 忽略。具体参数细节 参见 Windows CE.NET 帮助。函数返回创建或者打开的文件的句柄。

第二步:调用 CreateFileMapping 函数。这 个函数创建一个无名的或者有名的内存映射文件对象。参数 1 为文件句柄。这个值由 CreateFileForMapping 函数返回。参数 2 为安全属性(必 须设置为 NULL ),参数 3 指定要映射的文件的保护属性(只读或者读写),参数 4 和参数 5 共同用于指定要映射的文件的大小。文件的容量过大将导致 32 位整 数也不能表示,所以这里用 64 位变量表示,其中参数 4 为高 32 位数,参数 5 为低 32 位数。最后一个参数指定内存映射文件的名称。这里可以设置为 NULL 表示不需要名字。

第三步:调用 MapViewOfFile 函数。这个函数用于保留一段足够的地址空间,并且将永久存储器上的文件数据映射到这 个地址空间。映射后这段地址空间又叫做文件视图,映射范围可以是全部文件,也可以是部分文件。这里需要注意的是如果文件很大,那这个函数将在全局地址空间 内分配地址空间。参数 1 指定内存映射文件对象的句柄,这个值由 CreateFileMapping 函数返回。参数 2 CreateFileMapping 函数中参数 3 很相似,都是用于限定访问权限。参数 3 和参数 4 共同用于指定映射区域的开始位置。其中参数 3 为高 32 位数,参数 4 为低 32 位数。参数 5 指定映 射区域的大小。需要注意的是参数 3 和参数 4 指定的 64 位数开始位置可以不是 64KB 的倍数。而其它 Windows 操作系统就必须限制以 64KB 为单位。另 外还要注意的是帮助文档中说不能保证一个文件的映射视图是连续的,并建议为了防止访问非法,应该加入结构化异常处理机制。这个可能性我认为很小,一般对于 大于 2MB 的虚拟地址空间的申请,内核都会在全局地址空间中分配。全局地址空间( 0x4200 0000 0x7FFF FFFF )近 1GB 的空间应该足够用了。毕竟 Windows CE 下的文件都很小。不过在代码中加入结构化异常处理也不是坏事。我们应该养成凡是读写文件数据时都加入结构化异常处理的习惯。

第四步:进行读 / 写操作。 MapViewOfFile 函数如果成功执行,那么返回映射视图的首地址。这时就可以把视图当成是一个缓冲区,开始读或写操作了。

第五步:执行结束工作。先调用 UnmapViewOfFile 函数撤销文件映射视图。参数只有一个,指定视图首地址。然后调用 CloseHandle 函数关闭内存映射文件对象,参数为句柄。最后再次调用 CloseHandle 函数,关闭打开的文件的句柄。

5.2 进程之间通信

进程之间有时需要通信。系统提供的进程之间的通信机制比如 COM 、剪贴板等,在底层 实现上都是利用内存映射文件技术。其实进程之间通信的思路很简单,在这里我顺便讲一下。在其它 Windows 操作系统中,每个进程独自占有 4GB 的地址空 间,高 2GB 是内核的地址空间,而低 2GB 是进程的地址空间。一个进程所能访问的所有低 2GB 地址都是自己的地址空间,当访问内核地址空间时就会受到内核 的限制。这样一个进程当然无法访问其它进程了。为解决进程间通信的问题,内存映射文件技术被利用作为解决方案。原来内存映射文件只映射类似磁盘一类的存储 器上的文件。而为了更快速地在进程之间通信,内存映射文件还可以提交物理内存。实现方法是通过访问同一个内存映射文件对象(映射到物理内存),两个进程或 多个进程就能够访问到同一块物理内存,这样一个进程写到物理内存的数据,其它进程就能够看到了。而 Windows CE 虽然每个进程只占有 32MB 的地址空间,而且所有进程全部处于 4GB 的地址空间中,但是彼此还是不能够随意访问的。在 Windows CE 下除了使用内存映射文件技术外,还有一种方法也很适合使用,就是利用对象存储。对象存储本身使用 RAM 文件系统,用普通的操作文件的 API 就可以创 建、读取存在于对象存储区域内的文件。 /Windows 目录就存在于对象存储区域内。我们可以利用在 /Windows 目录下创建文件来实现进程间通信。这种方法既实现简单,只需调用几个文件 API 函数,又可以 减少通信时间,因为 /Windows 目录存在于物理内存中,数据 I/O 当然很快了。利用对象存储来实现进程之间的通信是我自己想出来的, MSDN 或其它文 档并没有这方面的说明。需要注意的就是对象存储区域的大小。另外从实现的代码量上看也不如内存映射文件技术。

下面讲解如何利用内存映射文件实现进程之间的通信。假设进程 A 和进程 B 需要通信,那么进程 A 需要先创建一个内存映射文件(之前不必调用 CreateFileForMapping 函数来创建文件,因为不需要创建文件)。这个内存映射文件可以是在永久存储器中,也可以是在内存中。为了减小通 信时间,最好提交物理内存。进程 A 在调用 CreateFileMapping 函数时,参数 1 指定为 INVALID_HANDLE_VALUE ,这表示这个 内存映射文件对象将要把物理内存提交到地址空间中。最后一个参数一定要指定一个名字。进程 B 也同样调用 CreateFileMapping 函数,而且参数 相同。内核会根据名字来判断是否已经存在一个内存映射文件对象,如果创建了就返回原来的对象的句柄。接下去就不用细说了。参照 5.1 去执行就可以了。要注 意的是进程 B 调用 CreateFileMapping 函数后要按如下代码检验函数执行结果:

HANDLE  hMap;
hMap = CreateFileMapping(INVALID_HANDLE_VALUE,
                        NULL,
                        PAGE_READWRITE,
                        0,
                        1000,
                        L"abc");
if (hMap == NULL || GetLastError() != ERROR_ALREADY_EXISTS)
{
        MessageBox(L"create file mapping fail");
        return;
}     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值