int main()
{
HANDLE hFileMap=CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,sizeof(DWORD),_T("hello"));
if(hFileMap==INVALID_HANDLE_VALUE)
{
if(ERROR_ALREADY_EXISTS!=GetLastError())
{
printf("创建文件映射内存内核对象失败\n");
return -1;
}
hFileMap=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hFileMap==NULL)
{
printf("打开文件视图错误\n");
return -1;
}
}
DWORD* pData=(DWORD*)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pData==NULL)
{
printf("映射文件失败\n");
return -1;
}
*pData=::GetCurrentThreadId();
CloseHandle(hFileMap);
getchar();
return 0;
}
另一个进程:
int main()
{
HANDLE hMapFile=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hMapFile==NULL)
{
printf("打开文件视图错误,错误码为:%d\n",GetLastError()); //错误码是2 ?????
return -1;
}
LPVOID pData=MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,sizeof(DWORD));
if(pData!=NULL)
printf("%s\n",(char*)pData);
CloseHandle(hMapFile);
getchar();
return 0;
}
14 个解决方案
#1
程序没问题!
问题当你运行第一个程序的时候,在运行第二个程序的时候
你第一个程序的共享内存已经被你关闭了
HANDLE hFileMap=CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,sizeof(DWORD),_T("hello"));
if(hFileMap==INVALID_HANDLE_VALUE)
{
if(ERROR_ALREADY_EXISTS!=GetLastError())
{
printf("创建文件映射内存内核对象失败\n");
return -1;
}
hFileMap=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hFileMap==NULL)
{
printf("打开文件视图错误\n");
return -1;
}
}
DWORD* pData=(DWORD*)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pData==NULL)
{
printf("映射文件失败\n");
return -1;
}
*pData=::GetCurrentThreadId();
getchar();
CloseHandle(hFileMap);
问题当你运行第一个程序的时候,在运行第二个程序的时候
你第一个程序的共享内存已经被你关闭了
HANDLE hFileMap=CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,sizeof(DWORD),_T("hello"));
if(hFileMap==INVALID_HANDLE_VALUE)
{
if(ERROR_ALREADY_EXISTS!=GetLastError())
{
printf("创建文件映射内存内核对象失败\n");
return -1;
}
hFileMap=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hFileMap==NULL)
{
printf("打开文件视图错误\n");
return -1;
}
}
DWORD* pData=(DWORD*)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pData==NULL)
{
printf("映射文件失败\n");
return -1;
}
*pData=::GetCurrentThreadId();
getchar();
CloseHandle(hFileMap);
#2
如LS所言,你应该设计一种协议,比如建立两个命名Event,在A中写完共享内存后设置EventA,然后等待EventB。B中等到这个事件,就去读取共享内存,B再设置EventB,等待EventA。这样就好了。
#3
1. 这个例子与我以前的一个帖子有一点的共性:
那个例子是子进程继承了父进程的一个句柄(父进程中创建了一个event),
我在父和子都调用了CloseHandle(事件)
毫无问题
2.现在说我对的答案的疑问:
两个进程使用 内存共享机制,那么这个内核对象,何时消失,回收?
当引用计数为0的时候!!
这个没争议吧。
第二个进程 打开这个句柄后,那么引用计数+1,没争议吧。
好了,
CloseHandle(hFileMap);
getchar();
只会导致该句柄无效,且减少次数! 如果没有第二个进程的话,那么引用计数为0了。
系统何时回收,似乎没有规定。这个不是重点需要关注的。
当 第二个进程打开后,引用计数为2了。 因为+1导致的。
所以,。似乎你说的没占到道理啊
#4
LZ可以做个实验,你运行你第一段代码,然后用Process Explorer查看你这个进程创建的共享内存是否还存在。从返回码看是
ERROR_FILE_NOT_FOUND
2 (0x2)
The system cannot find the file specified.
于是如果是权限问题,将返回的不是2。所以LZ最好实验一下,看看执行到哪步时那个共享内存没了。
ERROR_FILE_NOT_FOUND
2 (0x2)
The system cannot find the file specified.
于是如果是权限问题,将返回的不是2。所以LZ最好实验一下,看看执行到哪步时那个共享内存没了。
#5
修改部分代码后,打印 进程1的主线程id.
发现 结果不一样
int main()
{
HANDLE hFileMap=CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,sizeof(DWORD),_T("hello"));
if(hFileMap==INVALID_HANDLE_VALUE)
{
if(ERROR_ALREADY_EXISTS!=GetLastError())
{
printf("创建文件映射内存内核对象失败\n");
return -1;
}
hFileMap=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hFileMap==NULL)
{
printf("打开文件视图错误\n");
return -1;
}
}
DWORD* pData=(DWORD*)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pData==NULL)
{
printf("映射文件失败\n");
return -1;
}
*pData=::GetCurrentThreadId();
printf("当前线程的id为:%d\n",*pData);
getchar();
CloseHandle(hFileMap);
return 0;
}
int main()
{
HANDLE hMapFile=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hMapFile==NULL)
{
printf("打开文件视图错误,错误码为:%d\n",GetLastError());
return -1;
}
LPVOID pData=MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,sizeof(DWORD));
if(pData!=NULL)
printf("%d\n",(DWORD*)pData);
else
printf("映射的时候错误,错误码为:%d", GetLastError());
CloseHandle(hMapFile);
getchar();
return 0;
}
#6
你说的这个工具,查不到,原因:它根本就不能查找句柄
尽管有按这个功能
我不CloseHandle,都查不到
尽管有按这个功能
我不CloseHandle,都查不到
#7
if(pData!=NULL)
printf("%d\n", *(DWORD*)pData);
#8
额,好吧。打开Process Explorer,选中你的程序,View—>Low Pane View->Handles。
#9
内存是不是用完没释放
#10
说说偶地经验,几年前做过共享内存的实验。
进程1开共享,进程2获得进程映射之后,进程1退出,进程2原先获得句柄映射任然有效的。
进程1开共享,进程2获得进程映射之后,进程1退出,进程2原先获得句柄映射任然有效的。
#11
实验不对,可以拿我1楼的代码做实验,注意
进程1 注释 CloseHandle 这一句,进程1结束后,执行进程2
发现用打不开
说明:内核对象这种东西, 很可能进程结束,操作系统就回收了。
反过来再做实验:进程1用getchar保持着不接受, 进程2先接受,那么用楼上说的工具依然可以看到这个句柄
似乎一般的代码是无法做到获得 引用计数是多少?
还有在代码中 Closehandle 似乎只是一个好习惯,但不是必然要加的,操作系统当进程结束后,似乎就会及时回收。
进程1 注释 CloseHandle 这一句,进程1结束后,执行进程2
发现用打不开
说明:内核对象这种东西, 很可能进程结束,操作系统就回收了。
反过来再做实验:进程1用getchar保持着不接受, 进程2先接受,那么用楼上说的工具依然可以看到这个句柄
似乎一般的代码是无法做到获得 引用计数是多少?
还有在代码中 Closehandle 似乎只是一个好习惯,但不是必然要加的,操作系统当进程结束后,似乎就会及时回收。
#12
现在回答你的答复:
进程1没有结束,CloseHandle的作用只是起到减少引用次数,
我看过的书籍 并没有提到过 何时回收内核对象。
但是我做了实验发现后:
对于文件视图(内存共享方式锁产生的这种内核对象),当CloseHandle后,立即消失。
对于 事件内核对象也是如此。
以上说的有个前提:必须把内核对象命名,否则工具看不到。
但是:虽然工具看不到,不能够说明 就消失了,因为无名的内核对象也是看不到的(用工具)
///////////////////////////////////////////////////////////////////////////////////
进程1创建一个内核对象,进程2使用之。 目前的实验,似乎可以得出一个结论:进程1不能够CloseHandle
另外:进程2打开之前,必须保证进程1不结束。
回答 引用计数的疑问:似乎是在进程2打开时候,必须保证该内核对象的引用计数为1以上,否则一旦为0,那那么狠可能打开失败。
进程1没有结束,CloseHandle的作用只是起到减少引用次数,
我看过的书籍 并没有提到过 何时回收内核对象。
但是我做了实验发现后:
对于文件视图(内存共享方式锁产生的这种内核对象),当CloseHandle后,立即消失。
对于 事件内核对象也是如此。
以上说的有个前提:必须把内核对象命名,否则工具看不到。
但是:虽然工具看不到,不能够说明 就消失了,因为无名的内核对象也是看不到的(用工具)
///////////////////////////////////////////////////////////////////////////////////
进程1创建一个内核对象,进程2使用之。 目前的实验,似乎可以得出一个结论:进程1不能够CloseHandle
另外:进程2打开之前,必须保证进程1不结束。
回答 引用计数的疑问:似乎是在进程2打开时候,必须保证该内核对象的引用计数为1以上,否则一旦为0,那那么狠可能打开失败。
#13
为了保证完全回收内核对象, CloseHandle的用法,使用,似乎值得商榷。
请大神提供demo, 没有看懂,也不会实现你的意图。谢谢
如LS所言,你应该设计一种协议,比如建立两个命名Event,在A中写完共享内存后设置EventA,然后等待EventB。B中等到这个事件,就去读取共享内存,B再设置EventB,等待EventA。这样就好了。
请大神提供demo, 没有看懂,也不会实现你的意图。谢谢
#14
那我写段伪代码,你看着怎么完善吧。
int main()
{
HANDLE hFileMap=CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,sizeof(DWORD),_T("hello"));
if(hFileMap==INVALID_HANDLE_VALUE)
{
if(ERROR_ALREADY_EXISTS!=GetLastError())
{
printf("创建文件映射内存内核对象失败\n");
return -1;
}
hFileMap=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hFileMap==NULL)
{
printf("打开文件视图错误\n");
return -1;
}
}
DWORD* pData=(DWORD*)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pData==NULL)
{
printf("映射文件失败\n");
return -1;
}
*pData=::GetCurrentThreadId();
// 创建一个命名事件,用于通知对方:我写完了,你可以读取了
HANDLE hWriteReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GWriteReadyEvent");
if ( NULL != hWriteReadyEvent ) {
// 这儿喊了一声
SetEvent(hWriteReadyEvent );
}
// 创建一个命名事件,用于等待对方告诉我:他读完了,你可以继续你的工作了
HANDLE hReadReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GReadReadyEvent");
if ( NULL != hReadReadyEvent ) {
// 无限期等
DWORD dwWaitReson = WaitforSingleObject( hReadReadyEvent, INFINITE);
if ( WAIT_OBJECT_0 == dwWaitReson ) {
// 等成功了
}
else {
// 等失败了
}
}
// 这个你忘记加了
UnmapViewOfFile(hFileMap);
// 可以放心关了
CloseHandle(hFileMap);
hFileMap = NULL;
return 0;
}
另一个进程:
C/C++ code
int main()
{
// 打开(可能是创建)那个命名事件
HANDLE hWriteReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GWriteReadyEvent");
if ( NULL != hWriteReadyEvent ) {
// 无限等那个事件
DWORD dwWaitReson = WaitforSingleObject( hReadReadyEvent, INFINITE);
if ( WAIT_OBJECT == dwWaitReson ) {
// 成功等到了,可以读了
}
else {
// 等失败了,就不管了
return -1;
}
}
HANDLE hMapFile=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hMapFile==NULL)
{
printf("打开文件视图错误,错误码为:%d\n",GetLastError()); //错误码是2 ?????
return -1;
}
LPVOID pData=MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,sizeof(DWORD));
if(pData!=NULL)
printf("%s\n",(char*)pData);
// 这个你忘记加了
UnmapViewOfFile(hFileMap);
CloseHandle(hFileMap);
hFileMap = NULL;
HANDLE hReadReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GReadReadyEvent");
if ( NULL != hReadReadyEvent ) {
// 通知对方我读完了,你想干嘛就干嘛吧
SetEvent(hReadReadyEvent );
}
return 0;
}
没调试过,大概就是这个意思。
int main()
{
HANDLE hFileMap=CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,sizeof(DWORD),_T("hello"));
if(hFileMap==INVALID_HANDLE_VALUE)
{
if(ERROR_ALREADY_EXISTS!=GetLastError())
{
printf("创建文件映射内存内核对象失败\n");
return -1;
}
hFileMap=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hFileMap==NULL)
{
printf("打开文件视图错误\n");
return -1;
}
}
DWORD* pData=(DWORD*)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pData==NULL)
{
printf("映射文件失败\n");
return -1;
}
*pData=::GetCurrentThreadId();
// 创建一个命名事件,用于通知对方:我写完了,你可以读取了
HANDLE hWriteReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GWriteReadyEvent");
if ( NULL != hWriteReadyEvent ) {
// 这儿喊了一声
SetEvent(hWriteReadyEvent );
}
// 创建一个命名事件,用于等待对方告诉我:他读完了,你可以继续你的工作了
HANDLE hReadReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GReadReadyEvent");
if ( NULL != hReadReadyEvent ) {
// 无限期等
DWORD dwWaitReson = WaitforSingleObject( hReadReadyEvent, INFINITE);
if ( WAIT_OBJECT_0 == dwWaitReson ) {
// 等成功了
}
else {
// 等失败了
}
}
// 这个你忘记加了
UnmapViewOfFile(hFileMap);
// 可以放心关了
CloseHandle(hFileMap);
hFileMap = NULL;
return 0;
}
另一个进程:
C/C++ code
int main()
{
// 打开(可能是创建)那个命名事件
HANDLE hWriteReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GWriteReadyEvent");
if ( NULL != hWriteReadyEvent ) {
// 无限等那个事件
DWORD dwWaitReson = WaitforSingleObject( hReadReadyEvent, INFINITE);
if ( WAIT_OBJECT == dwWaitReson ) {
// 成功等到了,可以读了
}
else {
// 等失败了,就不管了
return -1;
}
}
HANDLE hMapFile=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hMapFile==NULL)
{
printf("打开文件视图错误,错误码为:%d\n",GetLastError()); //错误码是2 ?????
return -1;
}
LPVOID pData=MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,sizeof(DWORD));
if(pData!=NULL)
printf("%s\n",(char*)pData);
// 这个你忘记加了
UnmapViewOfFile(hFileMap);
CloseHandle(hFileMap);
hFileMap = NULL;
HANDLE hReadReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GReadReadyEvent");
if ( NULL != hReadReadyEvent ) {
// 通知对方我读完了,你想干嘛就干嘛吧
SetEvent(hReadReadyEvent );
}
return 0;
}
没调试过,大概就是这个意思。
#1
程序没问题!
问题当你运行第一个程序的时候,在运行第二个程序的时候
你第一个程序的共享内存已经被你关闭了
HANDLE hFileMap=CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,sizeof(DWORD),_T("hello"));
if(hFileMap==INVALID_HANDLE_VALUE)
{
if(ERROR_ALREADY_EXISTS!=GetLastError())
{
printf("创建文件映射内存内核对象失败\n");
return -1;
}
hFileMap=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hFileMap==NULL)
{
printf("打开文件视图错误\n");
return -1;
}
}
DWORD* pData=(DWORD*)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pData==NULL)
{
printf("映射文件失败\n");
return -1;
}
*pData=::GetCurrentThreadId();
getchar();
CloseHandle(hFileMap);
问题当你运行第一个程序的时候,在运行第二个程序的时候
你第一个程序的共享内存已经被你关闭了
HANDLE hFileMap=CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,sizeof(DWORD),_T("hello"));
if(hFileMap==INVALID_HANDLE_VALUE)
{
if(ERROR_ALREADY_EXISTS!=GetLastError())
{
printf("创建文件映射内存内核对象失败\n");
return -1;
}
hFileMap=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hFileMap==NULL)
{
printf("打开文件视图错误\n");
return -1;
}
}
DWORD* pData=(DWORD*)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pData==NULL)
{
printf("映射文件失败\n");
return -1;
}
*pData=::GetCurrentThreadId();
getchar();
CloseHandle(hFileMap);
#2
如LS所言,你应该设计一种协议,比如建立两个命名Event,在A中写完共享内存后设置EventA,然后等待EventB。B中等到这个事件,就去读取共享内存,B再设置EventB,等待EventA。这样就好了。
#3
1. 这个例子与我以前的一个帖子有一点的共性:
那个例子是子进程继承了父进程的一个句柄(父进程中创建了一个event),
我在父和子都调用了CloseHandle(事件)
毫无问题
2.现在说我对的答案的疑问:
两个进程使用 内存共享机制,那么这个内核对象,何时消失,回收?
当引用计数为0的时候!!
这个没争议吧。
第二个进程 打开这个句柄后,那么引用计数+1,没争议吧。
好了,
CloseHandle(hFileMap);
getchar();
只会导致该句柄无效,且减少次数! 如果没有第二个进程的话,那么引用计数为0了。
系统何时回收,似乎没有规定。这个不是重点需要关注的。
当 第二个进程打开后,引用计数为2了。 因为+1导致的。
所以,。似乎你说的没占到道理啊
#4
LZ可以做个实验,你运行你第一段代码,然后用Process Explorer查看你这个进程创建的共享内存是否还存在。从返回码看是
ERROR_FILE_NOT_FOUND
2 (0x2)
The system cannot find the file specified.
于是如果是权限问题,将返回的不是2。所以LZ最好实验一下,看看执行到哪步时那个共享内存没了。
ERROR_FILE_NOT_FOUND
2 (0x2)
The system cannot find the file specified.
于是如果是权限问题,将返回的不是2。所以LZ最好实验一下,看看执行到哪步时那个共享内存没了。
#5
修改部分代码后,打印 进程1的主线程id.
发现 结果不一样
int main()
{
HANDLE hFileMap=CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,sizeof(DWORD),_T("hello"));
if(hFileMap==INVALID_HANDLE_VALUE)
{
if(ERROR_ALREADY_EXISTS!=GetLastError())
{
printf("创建文件映射内存内核对象失败\n");
return -1;
}
hFileMap=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hFileMap==NULL)
{
printf("打开文件视图错误\n");
return -1;
}
}
DWORD* pData=(DWORD*)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pData==NULL)
{
printf("映射文件失败\n");
return -1;
}
*pData=::GetCurrentThreadId();
printf("当前线程的id为:%d\n",*pData);
getchar();
CloseHandle(hFileMap);
return 0;
}
int main()
{
HANDLE hMapFile=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hMapFile==NULL)
{
printf("打开文件视图错误,错误码为:%d\n",GetLastError());
return -1;
}
LPVOID pData=MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,sizeof(DWORD));
if(pData!=NULL)
printf("%d\n",(DWORD*)pData);
else
printf("映射的时候错误,错误码为:%d", GetLastError());
CloseHandle(hMapFile);
getchar();
return 0;
}
#6
你说的这个工具,查不到,原因:它根本就不能查找句柄
尽管有按这个功能
我不CloseHandle,都查不到
尽管有按这个功能
我不CloseHandle,都查不到
#7
if(pData!=NULL)
printf("%d\n", *(DWORD*)pData);
#8
额,好吧。打开Process Explorer,选中你的程序,View—>Low Pane View->Handles。
#9
内存是不是用完没释放
#10
说说偶地经验,几年前做过共享内存的实验。
进程1开共享,进程2获得进程映射之后,进程1退出,进程2原先获得句柄映射任然有效的。
进程1开共享,进程2获得进程映射之后,进程1退出,进程2原先获得句柄映射任然有效的。
#11
实验不对,可以拿我1楼的代码做实验,注意
进程1 注释 CloseHandle 这一句,进程1结束后,执行进程2
发现用打不开
说明:内核对象这种东西, 很可能进程结束,操作系统就回收了。
反过来再做实验:进程1用getchar保持着不接受, 进程2先接受,那么用楼上说的工具依然可以看到这个句柄
似乎一般的代码是无法做到获得 引用计数是多少?
还有在代码中 Closehandle 似乎只是一个好习惯,但不是必然要加的,操作系统当进程结束后,似乎就会及时回收。
进程1 注释 CloseHandle 这一句,进程1结束后,执行进程2
发现用打不开
说明:内核对象这种东西, 很可能进程结束,操作系统就回收了。
反过来再做实验:进程1用getchar保持着不接受, 进程2先接受,那么用楼上说的工具依然可以看到这个句柄
似乎一般的代码是无法做到获得 引用计数是多少?
还有在代码中 Closehandle 似乎只是一个好习惯,但不是必然要加的,操作系统当进程结束后,似乎就会及时回收。
#12
现在回答你的答复:
进程1没有结束,CloseHandle的作用只是起到减少引用次数,
我看过的书籍 并没有提到过 何时回收内核对象。
但是我做了实验发现后:
对于文件视图(内存共享方式锁产生的这种内核对象),当CloseHandle后,立即消失。
对于 事件内核对象也是如此。
以上说的有个前提:必须把内核对象命名,否则工具看不到。
但是:虽然工具看不到,不能够说明 就消失了,因为无名的内核对象也是看不到的(用工具)
///////////////////////////////////////////////////////////////////////////////////
进程1创建一个内核对象,进程2使用之。 目前的实验,似乎可以得出一个结论:进程1不能够CloseHandle
另外:进程2打开之前,必须保证进程1不结束。
回答 引用计数的疑问:似乎是在进程2打开时候,必须保证该内核对象的引用计数为1以上,否则一旦为0,那那么狠可能打开失败。
进程1没有结束,CloseHandle的作用只是起到减少引用次数,
我看过的书籍 并没有提到过 何时回收内核对象。
但是我做了实验发现后:
对于文件视图(内存共享方式锁产生的这种内核对象),当CloseHandle后,立即消失。
对于 事件内核对象也是如此。
以上说的有个前提:必须把内核对象命名,否则工具看不到。
但是:虽然工具看不到,不能够说明 就消失了,因为无名的内核对象也是看不到的(用工具)
///////////////////////////////////////////////////////////////////////////////////
进程1创建一个内核对象,进程2使用之。 目前的实验,似乎可以得出一个结论:进程1不能够CloseHandle
另外:进程2打开之前,必须保证进程1不结束。
回答 引用计数的疑问:似乎是在进程2打开时候,必须保证该内核对象的引用计数为1以上,否则一旦为0,那那么狠可能打开失败。
#13
为了保证完全回收内核对象, CloseHandle的用法,使用,似乎值得商榷。
请大神提供demo, 没有看懂,也不会实现你的意图。谢谢
如LS所言,你应该设计一种协议,比如建立两个命名Event,在A中写完共享内存后设置EventA,然后等待EventB。B中等到这个事件,就去读取共享内存,B再设置EventB,等待EventA。这样就好了。
请大神提供demo, 没有看懂,也不会实现你的意图。谢谢
#14
那我写段伪代码,你看着怎么完善吧。
int main()
{
HANDLE hFileMap=CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,sizeof(DWORD),_T("hello"));
if(hFileMap==INVALID_HANDLE_VALUE)
{
if(ERROR_ALREADY_EXISTS!=GetLastError())
{
printf("创建文件映射内存内核对象失败\n");
return -1;
}
hFileMap=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hFileMap==NULL)
{
printf("打开文件视图错误\n");
return -1;
}
}
DWORD* pData=(DWORD*)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pData==NULL)
{
printf("映射文件失败\n");
return -1;
}
*pData=::GetCurrentThreadId();
// 创建一个命名事件,用于通知对方:我写完了,你可以读取了
HANDLE hWriteReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GWriteReadyEvent");
if ( NULL != hWriteReadyEvent ) {
// 这儿喊了一声
SetEvent(hWriteReadyEvent );
}
// 创建一个命名事件,用于等待对方告诉我:他读完了,你可以继续你的工作了
HANDLE hReadReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GReadReadyEvent");
if ( NULL != hReadReadyEvent ) {
// 无限期等
DWORD dwWaitReson = WaitforSingleObject( hReadReadyEvent, INFINITE);
if ( WAIT_OBJECT_0 == dwWaitReson ) {
// 等成功了
}
else {
// 等失败了
}
}
// 这个你忘记加了
UnmapViewOfFile(hFileMap);
// 可以放心关了
CloseHandle(hFileMap);
hFileMap = NULL;
return 0;
}
另一个进程:
C/C++ code
int main()
{
// 打开(可能是创建)那个命名事件
HANDLE hWriteReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GWriteReadyEvent");
if ( NULL != hWriteReadyEvent ) {
// 无限等那个事件
DWORD dwWaitReson = WaitforSingleObject( hReadReadyEvent, INFINITE);
if ( WAIT_OBJECT == dwWaitReson ) {
// 成功等到了,可以读了
}
else {
// 等失败了,就不管了
return -1;
}
}
HANDLE hMapFile=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hMapFile==NULL)
{
printf("打开文件视图错误,错误码为:%d\n",GetLastError()); //错误码是2 ?????
return -1;
}
LPVOID pData=MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,sizeof(DWORD));
if(pData!=NULL)
printf("%s\n",(char*)pData);
// 这个你忘记加了
UnmapViewOfFile(hFileMap);
CloseHandle(hFileMap);
hFileMap = NULL;
HANDLE hReadReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GReadReadyEvent");
if ( NULL != hReadReadyEvent ) {
// 通知对方我读完了,你想干嘛就干嘛吧
SetEvent(hReadReadyEvent );
}
return 0;
}
没调试过,大概就是这个意思。
int main()
{
HANDLE hFileMap=CreateFileMapping((HANDLE)-1,NULL,PAGE_READWRITE,0,sizeof(DWORD),_T("hello"));
if(hFileMap==INVALID_HANDLE_VALUE)
{
if(ERROR_ALREADY_EXISTS!=GetLastError())
{
printf("创建文件映射内存内核对象失败\n");
return -1;
}
hFileMap=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hFileMap==NULL)
{
printf("打开文件视图错误\n");
return -1;
}
}
DWORD* pData=(DWORD*)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
if(pData==NULL)
{
printf("映射文件失败\n");
return -1;
}
*pData=::GetCurrentThreadId();
// 创建一个命名事件,用于通知对方:我写完了,你可以读取了
HANDLE hWriteReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GWriteReadyEvent");
if ( NULL != hWriteReadyEvent ) {
// 这儿喊了一声
SetEvent(hWriteReadyEvent );
}
// 创建一个命名事件,用于等待对方告诉我:他读完了,你可以继续你的工作了
HANDLE hReadReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GReadReadyEvent");
if ( NULL != hReadReadyEvent ) {
// 无限期等
DWORD dwWaitReson = WaitforSingleObject( hReadReadyEvent, INFINITE);
if ( WAIT_OBJECT_0 == dwWaitReson ) {
// 等成功了
}
else {
// 等失败了
}
}
// 这个你忘记加了
UnmapViewOfFile(hFileMap);
// 可以放心关了
CloseHandle(hFileMap);
hFileMap = NULL;
return 0;
}
另一个进程:
C/C++ code
int main()
{
// 打开(可能是创建)那个命名事件
HANDLE hWriteReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GWriteReadyEvent");
if ( NULL != hWriteReadyEvent ) {
// 无限等那个事件
DWORD dwWaitReson = WaitforSingleObject( hReadReadyEvent, INFINITE);
if ( WAIT_OBJECT == dwWaitReson ) {
// 成功等到了,可以读了
}
else {
// 等失败了,就不管了
return -1;
}
}
HANDLE hMapFile=OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("hello"));
if(hMapFile==NULL)
{
printf("打开文件视图错误,错误码为:%d\n",GetLastError()); //错误码是2 ?????
return -1;
}
LPVOID pData=MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,sizeof(DWORD));
if(pData!=NULL)
printf("%s\n",(char*)pData);
// 这个你忘记加了
UnmapViewOfFile(hFileMap);
CloseHandle(hFileMap);
hFileMap = NULL;
HANDLE hReadReadyEvent = CreateEvent(NULL, FALSE, FALSE, "GReadReadyEvent");
if ( NULL != hReadReadyEvent ) {
// 通知对方我读完了,你想干嘛就干嘛吧
SetEvent(hReadReadyEvent );
}
return 0;
}
没调试过,大概就是这个意思。