windows 核心编程中关于MapViewOfFile不太明白的地方,求指教。

mister_exia 2012-04-09 11:12:46

HANDLE hFile = CreateFile(...);
HANDLE hFileMapping = CreateFileMapping(hFile, ...);
PVOID pvFile = MapViewOfFile(hFileMapping, ...);
// Use the memory-mapped file.
UnmapViewOfFile(pvFile);
CloseHandle(hFileMapping);
CloseHandle(hFile);


The preceding code shows the "expected" method for manipulating memory-mapped files. However, what it does not show is that the system increments the usage counts of the file object and the file-mapping object when you call MapViewOfFile. This side effect is significant because it means that we could rewrite the preceding code fragment as follows:


HANDLE hFile = CreateFile(...);
HANDLE hFileMapping = CreateFileMapping(hFile, ...);
CloseHandle(hFile);
PVOID pvFile = MapViewOfFile(hFileMapping, ...);
CloseHandle(hFileMapping);
// Use the memory-mapped file.
UnmapViewOfFile(pvFile);


第一段代码应该是标准写法了,第二段代码有什么问题吗?标红的那句实在看不懂是啥意思。
...全文
324 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
Lactoferrin 2012-04-11
  • 打赏
  • 举报
回复
这只能说是写书的人太靠直观
fly4free 2012-04-11
  • 打赏
  • 举报
回复
那岂不是说,微软很坑爹吗?
Lactoferrin 2012-04-10
  • 打赏
  • 举报
回复
先看这个代码

HANDLE hFile = CreateFileW(L"D:\\Downloads\\fg.ini",GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
HANDLE hFileMapping = CreateFileMappingW(hFile,0,PAGE_READONLY,0,0,0);
PVOID pvFile = MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0);

printf("%x,%x,%x,%p\n",GetCurrentProcessId(),hFile,hFileMapping,pvFile);
getchar();
CloseHandle(hFileMapping);
CloseHandle(hFile);
puts("closed");
getchar();
getchar();
UnmapViewOfFile(pvFile);

执行closehandle之前的对象状况
lkd> .process 8997a5d0
Implicit process is now 8997a5d0
lkd> !handle 30

PROCESS 8997a5d0 SessionId: 0 Cid: 05a4 Peb: 7ffdd000 ParentCid: 055c
DirBase: 0a3c0280 ObjectTable: e187cd40 HandleCount: 13.
Image: cbtest.exe

Handle table at e1f85000 with 13 entries in use

0030: Object: 89937540 GrantedAccess: 00120089 Entry: e1f85060
Object: 89937540 Type: (89a16040) File
ObjectHeader: 89937528 (old version)
HandleCount: 1 PointerCount: 1
Directory Object: 00000000 Name: \Downloads\fg.ini {HarddiskVolume2}


lkd> !object 89937540
Object: 89937540 Type: (89a16040) File
ObjectHeader: 89937528 (old version)
HandleCount: 1 PointerCount: 1
Directory Object: 00000000 Name: \Downloads\fg.ini {HarddiskVolume2}
lkd> !handle 34

PROCESS 8997a5d0 SessionId: 0 Cid: 05a4 Peb: 7ffdd000 ParentCid: 055c
DirBase: 0a3c0280 ObjectTable: e187cd40 HandleCount: 13.
Image: cbtest.exe

Handle table at e1f85000 with 13 entries in use

0034: Object: e196e240 GrantedAccess: 000f0005 Entry: e1f85068
Object: e196e240 Type: (89a25040) Section
ObjectHeader: e196e228 (old version)
HandleCount: 1 PointerCount: 1


lkd> !object e196e240
Object: e196e240 Type: (89a25040) Section
ObjectHeader: e196e228 (old version)
HandleCount: 1 PointerCount: 1
执行close之后的对象状况
lkd> !object 89937540
Object: 89937540 Type: (bad0b0b0)
ObjectHeader: 89937528 (old version)
HandleCount: 0 PointerCount: 0
lkd> !object e196e240
Object: e196e240 Type: (bad0b0b0)
ObjectHeader: e196e228 (old version)
HandleCount: 0 PointerCount: 0
说明view并不需要文件对象和section对象的存在
由于其他程序的影响,文件对象和节对象可能存在,但不能保证
它们的关系见windows internals 5

如果仅仅是同一个进程用这些,当然没问题,但如果涉及到进程间通信,则必须予以考虑
下面的代码的OpenFileMapping不会成功,第二个CreateFileMapping得到的和第一个内容独立,如果这样的代码用于IPC则会与预料的不同

HANDLE sec=CreateFileMappingW((HANDLE)-1,0,PAGE_READWRITE,0,64,L"sec");
printf("%x\n",sec);
PVOID view = MapViewOfFile(sec,FILE_MAP_READ,0,0,0);
printf("%p\n",view);
CloseHandle(sec);
HANDLE sec2=OpenFileMappingW(FILE_MAP_WRITE,0,L"sec");
HANDLE sec3=CreateFileMappingW((HANDLE)-1,0,PAGE_READWRITE,0,64,L"sec");
printf("%x",sec2);
Lactoferrin 2012-04-10
  • 打赏
  • 举报
回复
这一下说不完,具体的看wrk或windows internals
mister_exia 2012-04-10
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

system increments the usage counts of the file object and the file-mapping object when you call MapViewOfFile
这句话可以忘掉
[/Quote]

为什么呢?能讲一下原因吗?
fly4free 2012-04-10
  • 打赏
  • 举报
回复
个人猜测

由于调用 UnmapViewOfFile 会导致系统 increments the usage counts of the file object and the file-mapping object

所以,这段代码涉及到的三个句柄,先关闭哪一个都可以。
(嗯……,至少第二段代码所示的调用顺序是没问题的)
向立天 2012-04-10
  • 打赏
  • 举报
回复
如果不关心内核对象的统计信息就直接关掉其句柄
不只是这个位置
《windows核心编程》很多地方都有提醒读者CloseHandle并没有关闭对象
只是影响引用计数
Lactoferrin 2012-04-10
  • 打赏
  • 举报
回复
system increments the usage counts of the file object and the file-mapping object when you call MapViewOfFile
这句话可以忘掉
Lactoferrin 2012-04-10
  • 打赏
  • 举报
回复
引用不一定是句柄,所以pointerCount>=HandleCount
只有pointercount=0才可能释放掉对象
mister_exia 2012-04-10
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

先看这个代码
C/C++ code

HANDLE hFile = CreateFileW(L"D:\\Downloads\\fg.ini",GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
HANDLE hFileMapping = CreateFileMappingW(hFile,0,PAGE_READONLY,0,0,0);
……
[/Quote]

pointerCount 和 HandleCount 哪一个才是引用计数呢?不是说MapViewOfFile会增加引用计数吗?那么为什么这两个值都为1呢?
Lactoferrin 2012-04-10
  • 打赏
  • 举报
回复
和copyonwrite无关
fly4free 2012-04-10
  • 打赏
  • 举报
回复
copy on write 和 5楼的讲述有没有什么关联?
(都看不懂啊……)
Lactoferrin 2012-04-10
  • 打赏
  • 举报
回复
事情没这么简单,不要管这句话,如果你不是非常清楚,总是使用像第一种的代码
Eleven 2012-04-09
  • 打赏
  • 举报
回复
上面那段话简单的说就是说调用MapViewOfFile会增加文件对象和文件映射对象的引用计数。

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧