views:

311

answers:

3

Hello,

I have two window form applications written in C, one holds a struct consisting of two integers, another will receive it using the CreateFileMapping.

Although not directly related I want to have three events in place so each of the processes can "speak" to each other, one saying that the first program has something to pass to the second, one saying the first one has closed and another saying the second one has closed.

What would be the best way about doing this exactly? I've looked at the MSDN entry for the CreateFileMapping operation but I'm still not sure as to how it should be done.

I didn't want to start implementing it without having some sort of clear idea as to what I need to do.

Thanks for your time.

+3  A: 

A file mapping does not seem like the best way to handle this. It has a lot of overhead for simply sending two integers in one direction. For something like that, I'd consider something like a pipe. A pipe automates most of the other details, so (for example) attempting to read or write a pipe that's been closed on the other end will fail and GetLastError() will return ERROR_BROKEN_PIPE. To get the equivalent of the third event (saying there's something waiting) you work with the pipe in overlapped mode. You can wait on the pipe handle itself (see caveats in the documentation) or use an OVERLAPPED structure, which includes a handle for an event.

Jerry Coffin
This pipe method seems to be a lot better than my original idea, do you know of any resources that provide further examples? A "Pipes for Dummies" so to speak.
Jamie Keeling
Also, each windows form is in a seperate project within the same solution. Will pipes still work under these conditions as they are not related to each other and are seperate.
Jamie Keeling
Yes, pipes are fine for communicating between separate programs. No, I'm afraid I don't know of a really simple guide to them -- sorry.
Jerry Coffin
A: 

You can use CreateSemaphore and provide a name for the last parameter to create a named semaphore. Processes can share that semaphore (the other process would use OpenSemaphore). One process signals when the data is ready and the other can wait on it.

Having said this, I have to agree with Jerry that using a pipe might be a lot simpler to get it working. On the other hand, using the shared memory approach with semaphores (or events) may translate more simply to other platforms (e.g., Linux) if it becomes necessary to port it.

Mark Wilkins
+1  A: 

In answer to your question of how you WOULD do it if you wanted to used Shared Memory, you could use a byte in the shared memory to communicate between the two processes. Here is some sample code. You can easily replace the wait loops with semaphores

/

/ 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;
}

The client process would be equivalent but the code in the else case following the call to MapViewOfFile() would look something like this:

        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]);
        }
AlanKley