C 两个进程之间的命名共享内存

C 两个进程之间的命名共享内存,c,winapi,file-mapping,C,Winapi,File Mapping,我正在尝试使用文件映射在C中构建一个客户机/服务器,虽然它还处于开发的早期阶段,但我在理解文件映射的确切工作原理时遇到了一些困难 我在我的服务器上创建了一个结构的文件映射,并在上面放置了一些数据,然后我的客户机打开映射文件a读取数据ok。然后,我的客户机写入数据供服务器读取,但服务器无法读取客户机数据,我不明白为什么,因为文件映射应该在两个进程之间同步。在这个阶段,我仍然没有使用event,但我认为这不需要它们(是吗?) 她就是我的密码 服务器: struct _HBACKUPSERVICE{

我正在尝试使用文件映射在C中构建一个客户机/服务器,虽然它还处于开发的早期阶段,但我在理解文件映射的确切工作原理时遇到了一些困难

我在我的服务器上创建了一个结构的文件映射,并在上面放置了一些数据,然后我的客户机打开映射文件a读取数据ok。然后,我的客户机写入数据供服务器读取,但服务器无法读取客户机数据,我不明白为什么,因为文件映射应该在两个进程之间同步。在这个阶段,我仍然没有使用event,但我认为这不需要它们(是吗?)

她就是我的密码

服务器:

struct _HBACKUPSERVICE{
    DWORD           dwServerProcessID;
    TCHAR           szWork[MAX_PATH];
    HANDLE          hMapFile;
};

PHBACKUPSERVICE pBuf = NULL;
HANDLE hMapFile;

hMapFile = CreateFileMapping(
    INVALID_HANDLE_VALUE,    // use paging file
    NULL,                    // default security
    PAGE_READWRITE,          // read/write access
    0,                       // maximum object size (high-order DWORD)
    sizeof(HBACKUPSERVICE),  // maximum object size (low-order DWORD)
    _T("MyService"));        // name of mapping object

if (/*phBackupService->*/hMapFile == NULL){
    _tprintf(TEXT("Could not create file mapping object (%d).\n"),
        GetLastError());
    return *pBuf;
}

pBuf = (PHBACKUPSERVICE)MapViewOfFile(
    hMapFile,               // handle to map object
    FILE_MAP_ALL_ACCESS,    // read/write permission
    0,
    0,
    sizeof(HBACKUPSERVICE));

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


// Populate backup service structure
pBuf->hMapFile = hMapFile;
pBuf->dwServerProcessID = GetCurrentProcessId();

// Wait for client
do{
    _tprintf(_T("\nServer: Waiting for work."));
    pBuf = (PHBACKUPSERVICE)MapViewOfFile(
        _BackupService.hMapFile,    // handle to map object
        FILE_MAP_ALL_ACCESS,        // read/write permission
        0,
        0,
        sizeof(HBACKUPSERVICE));
    if (StringCbLength(pBuf->szWork, 1 * sizeof(TCHAR), NULL) == S_OK){ Sleep(500); }
} while (StringCbLength(pBuf->szWork, 1 * sizeof(TCHAR), NULL) == S_OK); // ERROR: pBuf->szWork is always empty...

_tprintf(_T("Work from client: %s"), pBuf->szWork);
PHBACKUPSERVICE pBuf = NULL;
HANDLE hMapFile;

hMapFile = CreateFileMapping(
    INVALID_HANDLE_VALUE,    // use paging file
    NULL,                    // default security
    PAGE_READWRITE,          // read/write access
    0,                       // maximum object size (high-order DWORD)
    sizeof(HBACKUPSERVICE),  // maximum object size (low-order DWORD)
    _T("MyService"));        // name of mapping object

if (hMapFile == NULL){
    _tprintf(TEXT("Could not create file mapping object (%d).\n"),
        GetLastError());
    return NULL;
}

pBuf = (PHBACKUPSERVICE)MapViewOfFile(
    hMapFile,               // handle to map object
    FILE_MAP_ALL_ACCESS,    // read/write permission
    0,
    0,
    sizeof(HBACKUPSERVICE));

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

// Populate backup service structure
pBuf->hMapFile = hMapFile;
pBuf->dwServerProcessID = GetCurrentProcessId();
ZeroMemory(pBuf->szWork, sizeof(pBuf->szWork));

// Wait for client
_tprintf(_T("\nServer: Waiting for work."));
while (pBuf->szWork[0] == 0){ Sleep(500); }

_tprintf(_T("Work from client: %s"), pBuf->szWork);
客户:

HBACKUPSERVICE _BackupService;
HANDLE hMapFile;

hMapFile = OpenFileMapping(
    FILE_MAP_ALL_ACCESS,   // read/write access
    FALSE,                 // do not inherit the name
    _T("MyService"));          // name of mapping object

if (hMapFile == NULL)
{
    _tprintf(TEXT("Could not open file mapping object (%d).\n"),
        GetLastError());
}

BackupService= (PHBACKUPSERVICE)MapViewOfFile(
    hMapFile,               // handle to map object
    FILE_MAP_ALL_ACCESS,    // read/write permission
    0,
    0,
    sizeof(HBACKUPSERVICE));

_tprintf(_T("Server process id: %d"), _BackupService.dwServerProcessID);
_tprintf(_T("send work to server"));
StringCchCopy(_BackupService.szWork, STRSAFE_MAX_CCH, _T("Do work for me!!!!!!!!!!")); //ERROR: the server never sees this
PHBACKUPSERVICE BackupService = NULL;
HANDLE hMapFile;

hMapFile = OpenFileMapping(
    FILE_MAP_ALL_ACCESS,   // read/write access
    FALSE,                 // do not inherit the name
    _T("MyService"));          // name of mapping object

if (hMapFile == NULL)
{
    _tprintf(TEXT("Could not open file mapping object (%d).\n"),
        GetLastError());
}

BackupService = (PHBACKUPSERVICE)MapViewOfFile(
    hMapFile,               // handle to map object
    FILE_MAP_ALL_ACCESS,    // read/write permission
    0,
    0,
    sizeof(HBACKUPSERVICE));

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

_tprintf(_T("Server process id: %d"), BackupService->dwServerProcessID);
_tprintf(_T("send work to server"));
StringCchCopy(BackupService->szWork, MAX_PATH, _T("Do work for me!!!!!!!!!!"));

谢谢

您的服务器正在其读取循环中调用
MapViewOfFile()
,因此您正在映射越来越多的指针,而不是取消映射它们。最终,要映射的可用地址将用完。把它扔掉。在进入循环之前,应该使用已从第一个
MapViewOfFile()
获取的
pBuf
指针。只需映射视图一次

您的客户端根本没有将数据写入映射视图,而是将数据写入本地
HBACKUPSERVICE
变量,而不是映射视图。这就是服务器看不到数据的原因

试试这个:

常见的:

typedef struct _HBACKUPSERVICE {
    DWORD           dwServerProcessID;
    TCHAR           szWork[MAX_PATH];
    HANDLE          hMapFile;
} HBACKUPSERVICE, *PHBACKUPSERVICE;
服务器:

struct _HBACKUPSERVICE{
    DWORD           dwServerProcessID;
    TCHAR           szWork[MAX_PATH];
    HANDLE          hMapFile;
};

PHBACKUPSERVICE pBuf = NULL;
HANDLE hMapFile;

hMapFile = CreateFileMapping(
    INVALID_HANDLE_VALUE,    // use paging file
    NULL,                    // default security
    PAGE_READWRITE,          // read/write access
    0,                       // maximum object size (high-order DWORD)
    sizeof(HBACKUPSERVICE),  // maximum object size (low-order DWORD)
    _T("MyService"));        // name of mapping object

if (/*phBackupService->*/hMapFile == NULL){
    _tprintf(TEXT("Could not create file mapping object (%d).\n"),
        GetLastError());
    return *pBuf;
}

pBuf = (PHBACKUPSERVICE)MapViewOfFile(
    hMapFile,               // handle to map object
    FILE_MAP_ALL_ACCESS,    // read/write permission
    0,
    0,
    sizeof(HBACKUPSERVICE));

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


// Populate backup service structure
pBuf->hMapFile = hMapFile;
pBuf->dwServerProcessID = GetCurrentProcessId();

// Wait for client
do{
    _tprintf(_T("\nServer: Waiting for work."));
    pBuf = (PHBACKUPSERVICE)MapViewOfFile(
        _BackupService.hMapFile,    // handle to map object
        FILE_MAP_ALL_ACCESS,        // read/write permission
        0,
        0,
        sizeof(HBACKUPSERVICE));
    if (StringCbLength(pBuf->szWork, 1 * sizeof(TCHAR), NULL) == S_OK){ Sleep(500); }
} while (StringCbLength(pBuf->szWork, 1 * sizeof(TCHAR), NULL) == S_OK); // ERROR: pBuf->szWork is always empty...

_tprintf(_T("Work from client: %s"), pBuf->szWork);
PHBACKUPSERVICE pBuf = NULL;
HANDLE hMapFile;

hMapFile = CreateFileMapping(
    INVALID_HANDLE_VALUE,    // use paging file
    NULL,                    // default security
    PAGE_READWRITE,          // read/write access
    0,                       // maximum object size (high-order DWORD)
    sizeof(HBACKUPSERVICE),  // maximum object size (low-order DWORD)
    _T("MyService"));        // name of mapping object

if (hMapFile == NULL){
    _tprintf(TEXT("Could not create file mapping object (%d).\n"),
        GetLastError());
    return NULL;
}

pBuf = (PHBACKUPSERVICE)MapViewOfFile(
    hMapFile,               // handle to map object
    FILE_MAP_ALL_ACCESS,    // read/write permission
    0,
    0,
    sizeof(HBACKUPSERVICE));

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

// Populate backup service structure
pBuf->hMapFile = hMapFile;
pBuf->dwServerProcessID = GetCurrentProcessId();
ZeroMemory(pBuf->szWork, sizeof(pBuf->szWork));

// Wait for client
_tprintf(_T("\nServer: Waiting for work."));
while (pBuf->szWork[0] == 0){ Sleep(500); }

_tprintf(_T("Work from client: %s"), pBuf->szWork);
客户:

HBACKUPSERVICE _BackupService;
HANDLE hMapFile;

hMapFile = OpenFileMapping(
    FILE_MAP_ALL_ACCESS,   // read/write access
    FALSE,                 // do not inherit the name
    _T("MyService"));          // name of mapping object

if (hMapFile == NULL)
{
    _tprintf(TEXT("Could not open file mapping object (%d).\n"),
        GetLastError());
}

BackupService= (PHBACKUPSERVICE)MapViewOfFile(
    hMapFile,               // handle to map object
    FILE_MAP_ALL_ACCESS,    // read/write permission
    0,
    0,
    sizeof(HBACKUPSERVICE));

_tprintf(_T("Server process id: %d"), _BackupService.dwServerProcessID);
_tprintf(_T("send work to server"));
StringCchCopy(_BackupService.szWork, STRSAFE_MAX_CCH, _T("Do work for me!!!!!!!!!!")); //ERROR: the server never sees this
PHBACKUPSERVICE BackupService = NULL;
HANDLE hMapFile;

hMapFile = OpenFileMapping(
    FILE_MAP_ALL_ACCESS,   // read/write access
    FALSE,                 // do not inherit the name
    _T("MyService"));          // name of mapping object

if (hMapFile == NULL)
{
    _tprintf(TEXT("Could not open file mapping object (%d).\n"),
        GetLastError());
}

BackupService = (PHBACKUPSERVICE)MapViewOfFile(
    hMapFile,               // handle to map object
    FILE_MAP_ALL_ACCESS,    // read/write permission
    0,
    0,
    sizeof(HBACKUPSERVICE));

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

_tprintf(_T("Server process id: %d"), BackupService->dwServerProcessID);
_tprintf(_T("send work to server"));
StringCchCopy(BackupService->szWork, MAX_PATH, _T("Do work for me!!!!!!!!!!"));

最后,
TCHAR
对于跨流程边界的互操作是危险的。想象一下,如果ANSI应用程序尝试与UNICODE应用程序通信,会发生什么情况。他们不会同意您的
szWork
字段的格式,因此也不会同意您的
HBACKUPSERVICE
结构的字节大小。根据您的需要,您应该将
TCHAR
替换为
CHAR
WCHAR
,并在两端保持一致。

您确定您的客户实际上写得正确吗?您是否尝试读取刚才写入的内容?是的,客户端写入共享结构可能是缓存的问题,使服务器无法实际重新读取写入的内容。我不这么认为,结构映射到两个进程上的内存,因此理论上,两个进程都应该“看到”工作的相同对象:)谢谢。我害怕使用指针,因为我不知道它们在不同的进程中如何使用,但它完全起作用了。同样感谢您对TCHAR的介绍,但这只是学术性的,我们被要求使用Unicode。如果您被要求使用Unicode,那么您应该使用
WCHAR
CreateFileMappingW()
OpenFileMappingW()
wprintf()
StringCchCopyW()