Bash On WindowsとWin32の間で共有メモリしたらどうなるのか問題

クライアント版のWindows10にはWSL(Windows Subsystem For Linux)と呼ばれるLinuxカーネルエミュレータが搭載されており、これを使用したBash On WindowsとしてLinuxのバイナリ互換環境を提供している。
世間にはいろいろとこのWSLを使ってアプリケーション環境を作ろうという試みもある:

まぁこの辺はそのうちどうにかなるとして、現段階(= Anniversary Update)のWSLでWin32アプリとの共有メモリを実現するにはどうすれば良いのかを考える。
... で、いろいろ考えたんだけどNTFSRAMDISKを作り、そのファイルを双方でmmap(2)するが一番簡単なんじゃないかという結論になった。(一般にRAMDISKFAT32の方が微妙に高速なことが多いが、WSLにWindowsのファイルを見せるにはDrvFs経由で見せる必要があり、このDrvFSが今のところNTFSとReFSにしか対応していない - https://blogs.msdn.microsoft.com/wsl/2016/06/15/wsl-file-system-support/ )
NTFSRAMDISKはImDisk Toolkit( http://www.majorgeeks.com/files/details/imdisk_toolkit.html )等で簡単に生成できる。

適当に検証プログラムを書きCygwinとWSLのclangでビルドして(__builtin_cyclecount()がClangのintrinsicなので)、とりあえず期待通りメモリ内容が共有できていることが確認できた。
memsetからmsyncされるまでの間にprintf()を挟んでみると対向プロセスがmemsetしていく過程が観察できるため、普通のファイルI/Oでエミュレーションされているわけでは無さそうだ。

Retry @ 1121:2
Retry @ 1121:18432
Retry @ 1121:41472
Retry @ 1121:86528
Retry @ 1121:177152
Retry @ 1121:344576
Retry @ 1121:691200
Retry @ 1121:1517568
Retry @ 1121:3561472
  • Cygwin => WSLの順で起動

  • WSL => Cygwinの順で起動


微妙にパフォーマンスが違っているのが気になるな。。1.4GB/secくらい出るならそれなりに実用的に使えそうだ。もっとも、LoWeのようにソケットを使って通信するのが普通の方法で、どうせ大体のシチュエーションでは実際にデータを使うためにはコピーが必要なのであまり意味は無いような気がする。どっちにせよプロセス間の同期のためにソケットを使うことになる(そうしないとプロセス間共有semaphore等が実現できない)ので一緒にデータをpiggy-backした方が高速だと思う。
ちなみに、テストコードではmsync()をしているが、msync()を省略してもちゃんと動作する何故? (デカくてキャッシュに収まらないから。)
現状のInsider previewでは(何故かPosix shared memoryでなく)SysV shared memoryがサポートされているが、これをWin32からアクセスする方法は見当たらなかった。というかipcmkコマンドで複数の共有メモリを作ってもipcsコマンドで1つしか見えない等挙動が不審な気がする。先のPDFにあるように、WSL自体はWin32 <=> WSLプロセスの共有メモリ等も持っているらしく、常識的な方法での共有メモリがサポートされるのもそう遠くは無いように見える。