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

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

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

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

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

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


person Jamie Keeling    schedule 14.04.2010    source источник


Ответы (3)


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

person Jerry Coffin    schedule 14.04.2010
comment
Этот метод канала кажется намного лучше, чем моя первоначальная идея, знаете ли вы какие-либо ресурсы, которые предоставляют дополнительные примеры? А трубы для чайников так сказать. - person Jamie Keeling; 15.04.2010
comment
Кроме того, каждая форма окна находится в отдельном проекте в одном решении. Будут ли трубы работать в этих условиях, поскольку они не связаны друг с другом и являются отдельными? - person Jamie Keeling; 15.04.2010
comment
Да, каналы подходят для обмена данными между отдельными программами. Нет, боюсь, я не знаю по-настоящему простого руководства по ним - извините. - person Jerry Coffin; 15.04.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]);
        }
person AlanKley    schedule 15.04.2010

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

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

person Mark Wilkins    schedule 14.04.2010