创建文件视图的进程: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;}

解决方案 »

  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);

      

  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最好实验一下,看看执行到哪步时那个共享内存没了。
      

  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,都查不到
      

  7.   


    if(pData!=NULL)
            printf("%d\n", *(DWORD*)pData);
      

  8.   

    额,好吧。打开Process Explorer,选中你的程序,View—>Low Pane View->Handles。
      

  9.   

    实验不对,可以拿我1楼的代码做实验,注意进程1 注释 CloseHandle 这一句,进程1结束后,执行进程2
    发现用打不开说明:内核对象这种东西, 很可能进程结束,操作系统就回收了。反过来再做实验:进程1用getchar保持着不接受, 进程2先接受,那么用楼上说的工具依然可以看到这个句柄
    似乎一般的代码是无法做到获得 引用计数是多少?
    还有在代码中 Closehandle 似乎只是一个好习惯,但不是必然要加的,操作系统当进程结束后,似乎就会及时回收。
      

  10.   

    现在回答你的答复:进程1没有结束,CloseHandle的作用只是起到减少引用次数,我看过的书籍 并没有提到过 何时回收内核对象。
    但是我做了实验发现后: 对于文件视图(内存共享方式锁产生的这种内核对象),当CloseHandle后,立即消失。对于 事件内核对象也是如此。以上说的有个前提:必须把内核对象命名,否则工具看不到。
    但是:虽然工具看不到,不能够说明 就消失了,因为无名的内核对象也是看不到的(用工具)
    ///////////////////////////////////////////////////////////////////////////////////进程1创建一个内核对象,进程2使用之。 目前的实验,似乎可以得出一个结论:进程1不能够CloseHandle另外:进程2打开之前,必须保证进程1不结束。
    回答 引用计数的疑问:似乎是在进程2打开时候,必须保证该内核对象的引用计数为1以上,否则一旦为0,那那么狠可能打开失败。
      

  11.   

    为了保证完全回收内核对象,   CloseHandle的用法,使用,似乎值得商榷。如LS所言,你应该设计一种协议,比如建立两个命名Event,在A中写完共享内存后设置EventA,然后等待EventB。B中等到这个事件,就去读取共享内存,B再设置EventB,等待EventA。这样就好了。请大神提供demo, 没有看懂,也不会实现你的意图。谢谢
      

  12.   

    那我写段伪代码,你看着怎么完善吧。
    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++ codeint 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;}
    没调试过,大概就是这个意思。