命名共享内存 Windows API C++

3
我是一名有用的助手,可以为您翻译文本。
我正在尝试在两个进程之间共享一些数据。第一个进程将数据写入映射文件中,第二个进程读取它。
以下是我迄今为止的代码:
第一个进程:
    #include "stdafx.h"
    #include <Windows.h>
    #include <tlhelp32.h>
    #include <tchar.h>
    #include<stdio.h>

    #define BUF_SIZE 256

    int _tmain(int argc, _TCHAR* argv[]) {
    TCHAR szName[] = TEXT("Global\\MyFileMappingObject");
    LPTSTR szMsg = TEXT("MESS");

    HANDLE tokenH;
    TOKEN_PRIVILEGES tp;
    LUID luid;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenH)) {
        printf("OpenProcessToken error: %u\n", GetLastError());
        return FALSE;
    }
    if (!LookupPrivilegeValue(NULL, SE_CREATE_GLOBAL_NAME, &luid)) {
        printf("LookupPrivilegeValue error: %u\n", GetLastError());
        return FALSE;
    }
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!AdjustTokenPrivileges(tokenH, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) {
        printf("AdjustTokenPrivileges error: %u\n", GetLastError());
        return FALSE;
    }
    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        printf("The token does not have the specified privilege. \n");
        return FALSE;
    }
    CloseHandle(tokenH);

    HANDLE hMapFile;
    LPCTSTR pBuf;
    hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,  
        NULL,                    
        PAGE_READWRITE,        
        0,                      
        BUF_SIZE,                
        szName);
    if (hMapFile == NULL)
    {
        _tprintf(TEXT("Could not create file mapping object (%d).\n"),
        GetLastError());
        return 1;
    }
    pBuf = (LPTSTR)MapViewOfFile(hMapFile,   
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        BUF_SIZE);

    if (pBuf == NULL)
    {
        _tprintf(TEXT("Could not map view of file (%d).\n"),
        GetLastError());

        CloseHandle(hMapFile);

        return 1;
    }
    CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
    UnmapViewOfFile(pBuf);
    printf("Done\n");
    CloseHandle(hMapFile);
    return 0;
}

第二步骤:
#include "stdafx.h"
#include <Windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>
#pragma comment(lib, "user32.lib")

#define BUF_SIZE 256

int _tmain(int argc, _TCHAR* argv[])
{
    TCHAR szName[] = TEXT("Global\\MyFileMappingObject");
    HANDLE tokenH;
    TOKEN_PRIVILEGES tp;
    LUID luid;
    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenH);
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
        printf("LookupPrivilegeValue error: %u\n", GetLastError());
        return FALSE;
    }
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!AdjustTokenPrivileges(tokenH, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) {
        printf("AdjustTokenPrivileges error: %u\n", GetLastError());
        return FALSE;
    }
    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        printf("The token does not have the specified privilege. \n");
        return FALSE;
    }
    CloseHandle(tokenH);

    HANDLE hMapFile;
    LPCTSTR pBuf;
    hMapFile = OpenFileMapping(
        FILE_MAP_ALL_ACCESS,   // read/write access
        FALSE,                 // do not inherit the name
        szName);               // name of mapping object

    if (hMapFile == NULL)
    {
        _tprintf(TEXT("Could not open file mapping object (%d).\n"),
            GetLastError());
        return 1;
    }
    pBuf = (LPTSTR)MapViewOfFile(hMapFile, // handle to map object
        FILE_MAP_ALL_ACCESS,  // read/write permission
        0,
        0,
        BUF_SIZE);

    if (pBuf == NULL)
    {
        _tprintf(TEXT("Could not map view of file (%d).\n"),
            GetLastError());
        CloseHandle(hMapFile);
        return 1;
    }
    MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);
    UnmapViewOfFile(pBuf);
    CloseHandle(hMapFile);
    return 0;
}

第一个进程成功地写入了数据(我没有收到任何错误消息并获得了“完成”消息),但问题出在第二个进程上。 在“OpenFileMapping”之后,从getLastError获取的代码是2,表示文件不存在。我以管理员身份运行两个进程。
1个回答

4

错误2是ERROR_FILE_NOT_FOUND,意味着在调用OpenFileMapping()时,命名映射对象不存在。

为了在进程之间共享命名内核对象,两个进程需要同时运行。像其他命名内核对象(事件,互斥等)一样,映射对象有一个与其关联的引用计数,其中每个打开的句柄会增加引用计数。当所有句柄关闭后,该对象将被销毁。

因此,当第一个应用程序取消映射其视图并关闭其对映射对象的句柄时,如果第二个应用程序没有已经打开同一映射对象的句柄,那么该对象将被销毁。因此,在第二个应用程序尝试打开它时,对象将不再存在。


现在我想起来,这是有道理的。但我有一个新手问题:如何防止第一个程序停止? - Lerul Ler
显然,你需要在第一个应用程序中编写一些代码来等待某些东西,无论是检查条件是否为真的循环,还是睡眠等待信号,或者类似的东西。如果你希望第一个应用程序等待直到第二个应用程序消耗存储的值,一个选项是通过CreateEvent()创建一个命名事件对象,并通过WaitForSingleObject()等待它,然后第二个应用程序可以通过OpenEvent()打开该事件并通过SetEvent()发出信号。 - Remy Lebeau
只是好奇 - 所以在Windows上你不能真正创建一个“持久化”的共享内存 - 这个共享内存可以随时连接和断开任何进程吗? - SergeyA
3
@SergeyA:不,Windows中没有这样的选项。但是你可以创建一个在后台运行的服务,其唯一目的是创建共享内存并保持其打开状态,然后其他应用程序可以根据需要打开和读写该内存。必要时,该服务还可以创建命名互斥体/信号量,以便应用程序访问共享内存时提供同步。否则,对于持久性存储,您必须使用文件或注册表。 - Remy Lebeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接