Использование CreateFileMapping между двумя программами - C - PullRequest
1 голос
/ 15 апреля 2010

У меня есть два приложения в форме окна, написанные на C, одно содержит структуру, состоящую из двух целых чисел, другое получит ее с помощью CreateFileMapping.

Хотя это и не связано напрямую, я хочу иметь три события на месте, чтобы каждый из процессов мог «разговаривать» друг с другом, один сказал, что первая программа должна что-то передать второй, другой сказал, что первая закрыта, и другой говорит, что второй закрылся.

Как лучше всего это сделать? Я просмотрел запись MSDN для операции CreateFileMapping, но до сих пор не уверен, как это сделать.

Я не хотел начинать реализовывать это, не имея какого-то ясного представления о том, что мне нужно делать.

Спасибо за ваше время.

Ответы [ 3 ]

4 голосов
/ 15 апреля 2010

Сопоставление файлов не кажется лучшим способом справиться с этим. Он имеет много накладных расходов для простой отправки двух целых чисел в одном направлении. Для чего-то такого, я бы подумал, что-то вроде трубы. Канал автоматизирует большинство других деталей, поэтому (например) попытка чтения или записи канала, который был закрыт на другом конце, завершится неудачей, и GetLastError() вернет ERROR_BROKEN_PIPE. Чтобы получить эквивалент третьего события (скажем, что-то ждет), вы работаете с конвейером в режиме перекрытия. Вы можете дождаться самого дескриптора канала (см. Предостережения в документации) или использовать структуру OVERLAPPED, которая включает дескриптор для события.

2 голосов
/ 15 апреля 2010

В ответ на ваш вопрос о том, как бы вы это сделали, если бы вы хотели использовать общую память, вы можете использовать байт в общей памяти для связи между двумя процессами. Вот пример кода. Вы можете легко заменить циклы ожидания семафорами

/

/ SharedMemoryServer.cpp : Defines the entry point for the console application.
//

//#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <conio.h>      // getch()
#include <tchar.h>
#include "Aclapi.h"     // SE_KERNEL_OBJECT

#define SM_NAME "Global\\SharedMemTest"

#define SIGNAL_NONE 0
#define SIGNAL_WANT_DATA 1
#define SIGNAL_DATA_READY 2

#define BUFF_SIZE 1920*1200*4

struct MySharedData
{
    unsigned char Flag;
    unsigned char Buff[BUFF_SIZE];
};

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE hFileMapping = CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0, sizeof(MySharedData), SM_NAME);

    if (hFileMapping == NULL)
        printf ("CreateFileMapping failed");
    else
    {
        // Grant anyone access
        SetNamedSecurityInfo(SM_NAME, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, (PACL) NULL, NULL);
        MySharedData* pSharedData = (MySharedData *) MapViewOfFile(hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);


        printf("Waiting for instructions\n");
        while (pSharedData->Flag == SIGNAL_NONE)  // Wait to be signaled for data
            ;
       if (pSharedData->Flag == SIGNAL_WANT_DATA)
        {
            printf("Signal for data received\n");
            size_t len = sizeof(pSharedData->Buff);
            memset (pSharedData->Buff, 0xFF, len);
            pSharedData->Flag = SIGNAL_DATA_READY;
            printf("Data ready signal set\n");
            // Wait for data to be consumed or up to 10 seconds
            while (pSharedData->Flag != SIGNAL_NONE)
                ;
            printf("Data consumed signal detected\n");
        }
    }
    _getch();
    return 0;
}

Клиентский процесс будет эквивалентен, но код в другом случае после вызова MapViewOfFile () будет выглядеть примерно так:

        pSharedData->Flag = SIGNAL_WANT_DATA;  // Signal for data
        printf("Signal for data set\n");
        while (pSharedData->Flag != SIGNAL_DATA_READY)
            ;
        printf("Data ready signal detected\n");
        if (pSharedData->Flag == SIGNAL_DATA_READY)
        {
            // Dump the first 10 bytes
                printf ("Data received: %x %x %x %x %x %x %x %x %x %x\n",
                pSharedData->Buff[0], pSharedData->Buff[1], pSharedData->Buff[2],
                pSharedData->Buff[3], pSharedData->Buff[4], pSharedData->Buff[5],
                pSharedData->Buff[6], pSharedData->Buff[7], pSharedData->Buff[8],
                pSharedData->Buff[9]);
        }
0 голосов
/ 15 апреля 2010

Вы можете использовать CreateSemaphore и указать имя последнего параметра для создания именованного семафора. Процессы могут совместно использовать этот семафор (другой процесс будет использовать OpenSemaphore). Один процесс сигнализирует, когда данные готовы, а другой может ждать их.

Сказав это, я должен согласиться с Джерри, что использовать трубу может быть намного проще, чтобы заставить ее работать. С другой стороны, использование подхода с разделяемой памятью с семафорами (или событиями) может более просто привести к другим платформам (например, Linux), если возникнет необходимость его портирования.

...