【问题标题】:Using CreateFileMapping between two programs - C在两个程序之间使用 CreateFileMapping - C
【发布时间】:2011-02-08 03:21:53
【问题描述】:

我有两个用 C 编写的窗体应用程序,一个包含一个由两个整数组成的结构,另一个将使用 CreateFileMapping 接收它。

虽然没有直接关系,但我希望设置三个事件,以便每个进程可以相互“对话”,一个说第一个程序有东西要传递给第二个,一个说第一个程序已经关闭并且另一种说法是第二个已经关闭。

确切地做到这一点的最佳方法是什么?我查看了 CreateFileMapping 操作的 MSDN 条目,但我仍然不确定应该如何完成。

我不想在没有明确知道我需要做什么的情况下开始实施它。

感谢您的宝贵时间。

【问题讨论】:

    标签: c winapi shared-memory


    【解决方案1】:

    文件映射似乎不是处理此问题的最佳方法。它有很多的开销,用于简单地向一个方向发送两个整数。对于类似的东西,我会考虑像管道这样的东西。管道会自动执行大部分其他细节,因此(例如)尝试读取或写入另一端已关闭的管道将失败,GetLastError() 将返回 ERROR_BROKEN_PIPE。要获得相当于第三个事件(说有一些东西在等待),您可以在重叠模式下使用管道。您可以等待管道句柄本身(请参阅文档中的警告)或使用 OVERLAPPED 结构,其中包含事件句柄。

    【讨论】:

    • 这个管道方法似乎比我原来的想法好很多,你知道有什么资源可以提供更多的例子吗?可以说是“傻瓜管道”。
    • 此外,每个窗口窗体都位于同一解决方案中的单独项目中。管道在这些条件下是否仍然可以工作,因为它们彼此不相关并且是独立的。
    • 是的,管道很适合在不同的程序之间进行通信。不,恐怕我不知道有一个非常简单的指南——抱歉。
    【解决方案2】:

    在回答您的问题时,如果您想使用共享内存,您将如何做到这一点,您可以使用共享内存中的一个字节在两个进程之间进行通信。这是一些示例代码。您可以轻松地用信号量替换等待循环

    /

    / 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() 之后的 else 情况下的代码将如下所示:

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

    【讨论】:

      【解决方案3】:

      您可以使用CreateSemaphore 并为最后一个参数提供名称以创建命名信号量。进程可以共享该信号量(其他进程将使用 OpenSemaphore)。当数据准备好时,一个进程会发出信号,而另一个可以等待。

      话虽如此,我不得不同意 Jerry 的观点,即使用管道可能更容易让它工作。另一方面,如果有必要移植,使用带有信号量(或事件)的共享内存方法可以更简单地转换到其他平台(例如 Linux)。

      【讨论】:

        猜你喜欢
        • 2015-07-24
        • 2015-07-18
        • 2012-12-11
        • 1970-01-01
        • 2016-07-27
        • 1970-01-01
        • 2015-10-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多