内存映射文件mapping file:windows的C, C#实现

内存映射文件mapping file:windows的C, C#实现

C++ 发送端:先用CreateFileMapping()创建共享内存,pBuf是内存中的内容,将内容写入其中。例如,在程序路径下有图片sample.jpg,使用内存映射文件通过C++读取,再用C#读出内容并显示。

#include <cstdio>
#include <windows.h>
using namespace std;
 
#define BUF_SIZE 388160
const char szName[] = "fileMapping_01";    // 共享内存的名字
 
int main()
{
    char x;
    char msg[BUF_SIZE];
    // 创建共享文件句柄
    HANDLE hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,    // 物理文件句柄
        NULL,                    // 默认安全级别
        PAGE_READWRITE,          // 可读可写
        0,                       // 高位文件大小
        BUF_SIZE,                // 地位文件大小
        (LPCSTR)szName                   // 共享内存名称
        );
 
 
    char *pBuf = (char *)MapViewOfFile(
        hMapFile,            // 共享内存的句柄
        FILE_MAP_ALL_ACCESS, // 可读写许可
        0,
        0,
        BUF_SIZE
        );

    FILE *fp = fopen("sample.jpg","rb");

    int i=0;
    while(fscanf(fp,"%c",&pBuf[i])!=EOF)
    {
        i+=1;
    }
    pBuf[i]=0;
    fclose(fp);

    scanf("%c",&x);

    UnmapViewOfFile(pBuf);
    CloseHandle(hMapFile);
    return 0;
}

C#接收端:新建C#的winform项目,为button1编写click方法,读取共享内存中的内容,展示在picturebox1上。

using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.IO.MemoryMappedFiles;


namespace client_csharp
{
    public partial class Form1 : Form
    {
        const int BUF_SIZE = 388160;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {

            using (var mmf = MemoryMappedFile.OpenExisting("fileMapping_01"))
            {
                MemoryMappedViewAccessor viewAccessor = mmf.CreateViewAccessor(0, BUF_SIZE);
                
                byte[] charsInMMf = new byte[BUF_SIZE];
                viewAccessor.ReadArray<byte>(0, charsInMMf, 0, BUF_SIZE);
                var p = Image.FromStream(new MemoryStream(charsInMMf));
                pictureBox1.BackgroundImage = (Bitmap)p;
            }

        }
    }
}

另外,用C编写接收端,从中读数据输出到控制台:

#include <cstdio>
#include <windows.h>
using namespace std;
 
#define BUF_SIZE 1025
const char szName[] = "fileMapping_01";    // 共享内存的名字
 
int main()
{
    // 创建共享文件句柄
    HANDLE hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,    // 物理文件句柄
        NULL,                    // 默认安全级别
        PAGE_READWRITE,          // 可读可写
        0,                       // 高位文件大小
        BUF_SIZE,                // 地位文件大小
        (LPCSTR)szName                   // 共享内存名称
        );
 
 
    char *pBuf = (char *)MapViewOfFile(
        hMapFile,            // 共享内存的句柄
        FILE_MAP_ALL_ACCESS, // 可读写许可
        0,
        0,
        BUF_SIZE
        );
 
   
    printf("%s",pBuf);
   
 
    UnmapViewOfFile(pBuf);
    CloseHandle(hMapFile);
    return 0;
}

C#的发送端,类似,但C#的char是2字节的,若要与C进行字符上的通信,必须用byte进行数据流的交换,再对byte进行转换才可以。

using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
using System.Threading;
namespace sendfm
{
    
    class Program
    {
        public struct ServiceMsg
        {
            public int Id;
            public long NowTime;
        }
        static void Main(string[] args)
        {
            String shareName = "sharedMem";
            using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen(shareName, 1024000, MemoryMappedFileAccess.ReadWrite))
            {
                bool mutexCreated;
                //进程间同步
                var mutex = new Mutex(true, "testmapmutex", out mutexCreated);
                using (MemoryMappedViewStream stream = mmf.CreateViewStream()) //创建文件内存视图流
                {
                    var writer = new BinaryWriter(stream);
                    for (int i = 0; i < 5; i++)
                    {
                        writer.Write(10*i);
                        Console.WriteLine("{0}位置写入流:{0}", i);
                    }
                }

                mutex.ReleaseMutex();

                Console.WriteLine("启动状态服务,按【回车】读取共享内存数据");
                Console.ReadLine();

                mutex.WaitOne();
                using (MemoryMappedViewStream stream = mmf.CreateViewStream())
                {
                    var reader = new BinaryReader(stream);
                    for (int i = 0; i < 10; i++)
                    {
                        Console.WriteLine("{1}位置:{0}", reader.ReadInt32(), i);
                    }
                }

                using (MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor(1024, 10240))
                {
                    int colorSize = Marshal.SizeOf(typeof(ServiceMsg));
                    ServiceMsg color;
                    for (int i = 0; i < 50; i += colorSize)
                    {
                        accessor.Read(i, out color);
                        Console.WriteLine("{1}\tNowTime:{0}", new DateTime(color.NowTime), color.Id);
                    }
                }
                mutex.ReleaseMutex();
            }
        }
    }
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注