I'm working on an embedded system that aquires about 20 megs of data per second. My lower-level acquisition, control, and processing layer converts most of it into a handful of important values, but it can also be useful for the end user to get a view of a window of the unprocessed data.
I'm working on an ASP.NET front end in C# with mod-mono. I would like the server-side part of the ASP.NET page to be able to easily request the last half-second or so worth of data. The C++ code has real-time constraints, so I can't use message passing to respond - it could easily get bogged down by too many clients or someone quickly refreshing. I would like it to be able to place the data somewhere where any number of C# readers can access it as needed.
I'm picturing an area of shared memory with a rolling buffer of the least 16 or 32MB of data. The C++ code is constantly updating it, and the C# code can peek at it whenever it wants to. Is there a way to handle this? All the information I find on using memory-mapped files seems to focus on forking a child, rather than having two unrelated processes use it for IPC - does it have to hit the disk (or fs cache, etc) before the C# application can see it, or does memory mapping from the two programs actually make them share the same pages?
Is there a way of accessing POSIX shared memory objects in C#?
Here, an example with C program and C# program sharing information (two different processes) by means of a memory-mapped file:
From console create file: dd if=/dev/zero of=/tmp/sharedfile bs=12288 count=1
The C# program:
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 ();
                     }
                }
            }
        }
    }
}
The C program:
#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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With