Windows 进程间通信(八)共享内存(FileMapping)

 

这时我们使用文件映射实现共享内存。

FileMapping用于将存在于磁盘的文件放进一个进程的虚拟地址空间,并在该进程的虚拟地址空间中产生一个区域用于存放该文件,这个空间就叫做File View,系统并同时产生一个File Mapping Object(存放于物理内存中)用于维持这种映射关系,这样当多个进程需要读写那个文件的数据时,它们的File View其实对应的都是同一个File  Mapping  Object,这样做可节省内存和保持数据的同步性,并达到数据共享的目的。

当然在一个应用向文件中写入数据时,其它进程不应该去读取这个正在写入的数据。这就需要进行一些同步的操作。

下边来看一下具体的API

  
  CreateFileMaping
 的用法:  
  HANDLE   CreateFileMapping(                           //
返回File   Mapping   Object的句柄  
      HANDLE   hFile,                                          //  
 想要产生映射的文件的句柄  
      LPSECURITY_ATTRIBUTES   lpAttributes,     //  
 安全属性(只对NT2000生效)  
      DWORD   flProtect,                                    //  
 保护标致  
      DWORD   dwMaximumSizeHigh,                  //  
 DWORD的高位中存放       

      File Mapping  Object                                  //    的大小  
      DWORD   dwMaximumSizeLow,                   //  
 DWORD的低位中存放

      File Mapping Object                                     //    的大小(通常这两个参数有一个为0    
      LPCTSTR   lpName                                     //   File   Mapping   Object
的名称。  
  );  

 

1) 物理文件句柄
   
 任何可以获得的物理文件句柄,如果你需要创建一个物理文件无关的内存映射也无妨,将它设置成为0xFFFFFFFF(INVALID_HANDLE_VALUE)就可以了.

如果需要和物理文件关联,要确保你的物理文件创建的时候的访问模式和"保护设置"匹配,比如: 物理文件只读,内存映射需要读写就会发生错误。推荐你的物理文件使用独占方式创建。

如果使用 INVALID_HANDLE_VALUE,也需要设置需要申请的内存空间的大小,无论物理文件句柄参数是否有效,这样 CreateFileMapping 就可以创建一个和物理文件大小无关的内存空间给你, 甚至超过实际文件大小,如果你的物理文件有效,而大小参数为0,则返回给你的是一个和物理文件大小一样的内存空间地址范围。返回给你的文件映射地址空间是可以通过复制,集成或者命名得到,初始内容为0

2) 保护设置
  
 就是安全设置, 不过一般设置NULL就可以了, 使用默认的安全配置. win2k下如果需要进行限制, 这是针对那些将内存文件映射共享给整个网络上面的应用进程使用是, 可以考虑进行限制.

3) 高位文件大小
32
位地址空间, 设置为0
4)
 共享内存名称

命名可以包含 "Global" 或者 "Local" 前缀在全局或者会话名空间初级文件映射. 其他部分可以包含任何除了()以外的字符, 可以参考 Kernel Object Name Spaces.

5) 调用CreateFileMapping的时候GetLastError的对应错误
   ERROR_FILE_INVALID    
 如果企图创建一个零长度的文件映射, 应有此报
   ERROR_INVALID_HANDLE  
 如果发现你的命名内存空间和现有的内存映射, 互斥量, 信号量, 临界区同名就麻烦了
   ERROR_ALREADY_EXISTS  
 表示内存空间命名已经存在

使用函数CreateFileMapping创建一个想共享的文件数据句柄,然后使用MapViewOfFile来获取共享的内存地址,然后使用OpenFileMapping函数在另一个进程里打开共享文件的名称,这样就可以实现不同的进程共享数据。

下边是C#是对使用的接口函数声明:

 

[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)]

public static extern IntPtr CreateFile(string lpFileName,

    int dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes,

    int dwCreationDisposition, int dwFlagsAndAttributes,

    IntPtr hTemplateFile);

 

[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)]

public static extern IntPtr CreateFileMapping(IntPtr hFile,

    IntPtr lpAttributes, int flProtect,

    int dwMaximumSizeLow, int dwMaximumSizeHigh, string lpName);

 

[DllImport("kernel32", SetLastError = true)]

public static extern bool FlushViewOfFile(IntPtr lpBaseAddress,

    IntPtr dwNumBytesToFlush);

 

[DllImport("kernel32", SetLastError = true)]

public static extern IntPtr MapViewOfFile(

    IntPtr hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh,

    int dwFileOffsetLow, IntPtr dwNumBytesToMap);

 

[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)]

public static extern IntPtr OpenFileMapping(

    int dwDesiredAccess, bool bInheritHandle, string lpName);

 

[DllImport("kernel32", SetLastError = true)]

public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);

 

[DllImport("kernel32", SetLastError = true)]

public static extern bool CloseHandle(IntPtr handle);

 

 

 

我们在示例里Server端建立的一个FileMapping,命名为:@"Global\MyFileMappingObject";这样我们在Client端就可以打开同名的FileMapping

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值