当然在一个应用向文件中写入数据时,其它进程不应该去读取这个正在写入的数据。这就需要进行一些同步的操作。
下边来看一下具体的API。
CreateFileMaping 的用法:
HANDLE CreateFileMapping( //返回File Mapping Object的句柄
HANDLE hFile, // 想要产生映射的文件的句柄
LPSECURITY_ATTRIBUTES lpAttributes, // 安全属性(只对NT和2000生效)
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函数在另一个进程里打开共享文件的名称,这样就可以实现不同的进程共享数据。
[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("