C到C#(Mono)内存映射文件/ linux中的共享内存

时间:2015-01-08 14:20:05

标签: c# c++ linux mono shared-memory

我正在研究一种每秒需要大约20兆的数据的嵌入式系统。我的低级采集,控制和处理层将其中的大部分转换为少数几个重要值,但它也可以帮助最终用户查看未处理数据的窗口。

我正在使用mod-mono在C#中使用ASP.NET前端。我希望ASP.NET页面的服务器端部分能够轻松地请求最后半秒左右的数据。 C ++代码具有实时约束,因此我不能使用消息传递来响应 - 它可能很容易被太多客户端或快速刷新的人陷入困境。我希望它能够将数据放在任何数量的C#读者可以根据需要访问它的地方。

我正在想象一个共享内存区域,其中包含至少16或32MB数据的滚动缓冲区。 C ++代码不断更新它,C#代码可以随时查看它。有办法处理这个吗?我在使用内存映射文件时发现的所有信息似乎都集中在分支一个孩子,而不是让两个不相关的进程将它用于IPC - 它是否必须在C#应用程序看到之前到达磁盘(或fs缓存等)它,或两个程序的内存映射实际上使它们共享相同的页面?

有没有办法在C#中访问POSIX共享内存对象?

1 个答案:

答案 0 :(得分:6)

这里,通过内存映射文件的C程序和C#程序共享信息(两个不同的进程)的示例:

  1. 从控制台创建文件:dd if = / dev / zero of = / tmp / sharedfile bs = 12288 count = 1

  2. C#程序:

    using System;
    using System.IO;
    using System.IO.MemoryMappedFiles;
    using System.Threading;
    
    namespace FileSharedMemory
    {
        class MainClass
        {
            public static void Main (string[] args)
            {
    
                using (var mmf = MemoryMappedFile.CreateFromFile("/tmp/sharedfile", FileMode.OpenOrCreate, "/tmp/sharedfile"))
                {
                    using (var stream = mmf.CreateViewStream ()) {
                        // 1. C program, filled memory-mapped file with the 'G' character (200 characters)
                        var data = stream.ReadByte ();
                        while (data != -1)
                        {
                            Console.WriteLine ((char)data);
                            data = stream.ReadByte ();
                         }
    
                         // 2. We write "Goose" at the beginning of memory-mapped file.
                         stream.Position = 0;
                         var buffer = new byte[] { 0x47, 0x6F, 0x6F, 0x73, 0x65 };
                         stream.Write (buffer, 0, 5);
    
                         Thread.Sleep (20000);
    
                         // 3. C program, filled memory-mapped file with the 'H' character (200 characters)
                         stream.Position = 0;
                         data = stream.ReadByte ();
                         while (data != -1)
                         {
                             Console.WriteLine ((char)data);
                             data = stream.ReadByte ();
                         }
                    }
                }
            }
        }
    }
    
  3. C程序:

    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/mman.h>
    #include <errno.h>
    
    int main(int argc, char *argv[])
    {
        int fd;
        int index;
        char *data;
        const char *filepath = "/tmp/sharedfile";
    
        if ((fd = open(filepath, O_CREAT|O_RDWR, (mode_t)00700)) == -1) {
            perror("open");
            exit(EXIT_FAILURE);
        }
    
        data = mmap(NULL, 12288, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
        if (data == MAP_FAILED) {
            perror("mmap");
            exit(EXIT_FAILURE);
        }
    
    
        for (index= 0; index < 200; index++) {
            data[index] = 'G';
        } 
    
        sleep(10);
    
        // We must see 'Goose' at the beginning of memory-mapped file.
        for (index= 0; index < 200; index++) {
            fprintf(stdout, "%c", data[index]);
        }
    
        for (index= 0; index < 200; index++) {
            data[index] = 'H';
        }
    
        if (msync(data, 12288, MS_SYNC) == -1) {
            perror("Error sync to disk");
        } 
    
        if (munmap(data, 12288) == -1) {
            close(fd);
            perror("Error un-mmapping");
            exit(EXIT_FAILURE);
        }
    
        close(fd);
    
        return 0;
    }