内存映射文件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();
}
}
}
}