WindowsのMemory Mapped Fileはx86とx64のデータの橋渡しにも使える場合が多い
.NETのMemory Mapped Fileを扱うプログラムを書いていたら,32bitも64bitも混ざっていたがどうもやり取りはできるらしい.
Windowsでは共有メモリとしてMemory Mapped Fileを使うと複数のプロセスから同じメモリ領域を参照しているような動作が可能になる.
.NET Framework 4.0からはサポートするクラスが用意されているので比較的簡単に利用できる.
ただし,.NETではターゲットがAny CPUだと32bit用のつもりのものが64bit環境で動いたり,逆も起こる.
このときどうなるのか気になっていたが,概ね問題なく動作する.
概ねというのは一つ一つの変数のアドレスを指定したバイト単位の参照の場合には問題ないということ.おそらく一度に参照しようとした場合には考慮すべきことが増えるのではないかと思うので後で調べる.
例えば,以下のようなコード
// サーバ側
using System;
using System.Windows.Forms;
using System.IO.MemoryMappedFiles;
namespace MemoryMappedFile_TEST
{
public partial class ServerForm : Form
{
private MemoryMappedFile mem = null;
private MemoryMappedViewAccessor accessor = null;
private Timer timer = new Timer();
private Int64 counter = 0;
public ServerForm()
{
InitializeComponent();
this.FormClosed += ServerForm_FormClosed;
mem = MemoryMappedFile.CreateNew("test_memory", 64);
accessor = mem.CreateViewAccessor();
this.label1.Text = counter.ToString();
timer.Interval = 1000;
timer.Tick += timer_Tick;
timer.Start();
}
private void ServerForm_FormClosed(object sender, FormClosedEventArgs e)
{
timer.Stop();
accessor.Dispose();
}
private void timer_Tick(object sender, EventArgs e)
{
// 書き込み
accessor.Write((Int64)0, (Int64)counter++);
this.label1.Text = counter.ToString();
}
}
}
// クライアント側
using System;
using System.Windows.Forms;
using System.IO.MemoryMappedFiles;
namespace Client
{
public partial class UserForm : Form
{
private MemoryMappedFile mem = null;
private MemoryMappedViewAccessor accessor = null;
private Timer timer = new Timer();
private Int64 value = 0;
public UserForm()
{
InitializeComponent();
this.FormClosed += UserForm_FormClosed;
mem = MemoryMappedFile.OpenExisting("test_memory");
accessor = mem.CreateViewAccessor();
this.label1.Text = value.ToString();
timer.Interval = 1000;
timer.Tick += timer_Tick;
timer.Start();
}
private void UserForm_FormClosed(object sender, FormClosedEventArgs e)
{
timer.Stop();
accessor.Dispose();
}
private void timer_Tick(object sender, EventArgs e)
{
// 書き込み
value = accessor.ReadInt64((Int64)0);
this.label1.Text = value.ToString();
}
}
}

