ロボット、千葉ロッテマリーンズについていいかげんなことを書きます。
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
どうにも共有メモリについて根本的な勘違いをしていたみたいなのでメモしておきます。
間違ったことを書いている可能性が高いので、気づいたら指摘してください。
まずWindowsでCreateFileMappingやMapViewOfFileを使用してプロセス間通信を実装すると、ファイルを介して情報をやりとりするという事になるようです。
どこかにファイルを作成して、そのファイルの内容を実行しているプロセスの仮想アドレスにマッピングする事であたかもメモリのように操作できるという事らしいです。
このサイトの図2のようなイメージです。
WIndowsでは以下のソースコードです。
HANDLE fh=CreateFile("MapFile",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL);
HANDLE hMap = CreateFileMapping(fh , NULL , PAGE_READWRITE , 0 , 4 , NULL);
void* pshared = MapViewOfFile( hMap, FILE_MAP_ALL_ACCESS, 0, 0, 4 );
reinterpret_cast<int*>(pshared)[0] = 100;
UnmapViewOfFile( pshared );
CloseHandle( hMap );
CloseHandle(fh);
ちなみにCreateFileMappingの引数を変更すると仮想メモリに領域を確保
するようにできるらしいです。
HANDLE hMap = CreateFileMapping((HANDLE)0xFFFFFFFF , NULL , PAGE_READWRITE , 0 , 4 , ”MapFile”);
こうすればファイルの正確な場所が分からなくても空間名さえ分かっていればアクセスできるという事になります。
Linuxでは以下のソースコードに対応すると思います。
const int fd=open("MapFile",O_RDWR|O_CREAT,0666)
int *ptr=(int *)mmap(0,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
ptr[0] = 100;
munmap(ptr,4);
close(fd);
Pythonではmmapというライブラリで実装できます。
Windowsの場合、ファイルハンドルに0と空間名を与えると上と同じく仮想メモリに領域を確保するみたいです。
shmem = mmap.mmap(0, 4, 'MapFile')
結局のところハードディスク上のファイルを介して他のプロセスと情報のやり取りを行うので、通信速度は遅いように思えますが、それでもソケット通信等に比べれば圧倒的に速いみたいです。自分の環境で比較しただけなので確実な事は言えませんけど。
ここまではファイルの内容をマッピングする方法ですが、以下の方法もあるようです。
まずWindowsではReadProcessMemory関数、WriteProcessMemory関数を使用する事で他のプロセスの仮想アドレスに直接アクセスできるらしいです。
Linuxではshm_open関数、shmget関数等で共有メモリが使えるらしいです。
この場合、ファイルは/dev/shm以下に作成されます。この/dev/shmはディスク上ではなくメモリにマウントされているので高速な通信ができるらしいです。
つまりshm_open関数で/dev/shm/MapFIleを作成すると、一見ディスク上にファイルが作成されたように見えますが実はメモリ上で操作しているという事になります。
そして作成した/dev/shm/MapFIleを上と同じくmmapで仮想アドレスにマッピングすると、共有メモリとして扱えるようになります。
・・・・・ということで合っていますでしょうか?
ちなみに以下のコードで実装できます。
const int fd = shm_open( 'MapFile', O_RDWR|O_CREAT, 0 );
ftruncate( fd , 4);
void* ptr = mmap( NULL, 4, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );
ptr[0] = 100;
munmap(ptr,4);
close( fd );
shm_unlink( 'MapFile' );
見て分かる通り、mmapの引数に入れるファイルディスクリプタを変更するだけです。
Pythonの場合は以下のコードで実装できます。
rt.close( fd )
rt.shm_unlink('MapFile')
間違ったことを書いている可能性が高いので、気づいたら指摘してください。
まずWindowsでCreateFileMappingやMapViewOfFileを使用してプロセス間通信を実装すると、ファイルを介して情報をやりとりするという事になるようです。
どこかにファイルを作成して、そのファイルの内容を実行しているプロセスの仮想アドレスにマッピングする事であたかもメモリのように操作できるという事らしいです。
このサイトの図2のようなイメージです。
WIndowsでは以下のソースコードです。
HANDLE fh=CreateFile("MapFile",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL);
HANDLE hMap = CreateFileMapping(fh , NULL , PAGE_READWRITE , 0 , 4 , NULL);
void* pshared = MapViewOfFile( hMap, FILE_MAP_ALL_ACCESS, 0, 0, 4 );
reinterpret_cast<int*>(pshared)[0] = 100;
UnmapViewOfFile( pshared );
CloseHandle( hMap );
CloseHandle(fh);
ちなみにCreateFileMappingの引数を変更すると仮想メモリに領域を確保
するようにできるらしいです。
HANDLE hMap = CreateFileMapping((HANDLE)0xFFFFFFFF , NULL , PAGE_READWRITE , 0 , 4 , ”MapFile”);
こうすればファイルの正確な場所が分からなくても空間名さえ分かっていればアクセスできるという事になります。
Linuxでは以下のソースコードに対応すると思います。
const int fd=open("MapFile",O_RDWR|O_CREAT,0666)
int *ptr=(int *)mmap(0,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
ptr[0] = 100;
munmap(ptr,4);
close(fd);
Pythonではmmapというライブラリで実装できます。
f = open('MapFile', 'r+')
m = mmap.mmap(f.fileno(), 4)
value = struct.pack("i",100)
value = struct.pack("i",100)
m.write(value)
m.close()
f.close()
Windowsの場合、ファイルハンドルに0と空間名を与えると上と同じく仮想メモリに領域を確保するみたいです。
shmem = mmap.mmap(0, 4, 'MapFile')
結局のところハードディスク上のファイルを介して他のプロセスと情報のやり取りを行うので、通信速度は遅いように思えますが、それでもソケット通信等に比べれば圧倒的に速いみたいです。自分の環境で比較しただけなので確実な事は言えませんけど。
ここまではファイルの内容をマッピングする方法ですが、以下の方法もあるようです。
まずWindowsではReadProcessMemory関数、WriteProcessMemory関数を使用する事で他のプロセスの仮想アドレスに直接アクセスできるらしいです。
Linuxではshm_open関数、shmget関数等で共有メモリが使えるらしいです。
この場合、ファイルは/dev/shm以下に作成されます。この/dev/shmはディスク上ではなくメモリにマウントされているので高速な通信ができるらしいです。
つまりshm_open関数で/dev/shm/MapFIleを作成すると、一見ディスク上にファイルが作成されたように見えますが実はメモリ上で操作しているという事になります。
そして作成した/dev/shm/MapFIleを上と同じくmmapで仮想アドレスにマッピングすると、共有メモリとして扱えるようになります。
・・・・・ということで合っていますでしょうか?
ちなみに以下のコードで実装できます。
const int fd = shm_open( 'MapFile', O_RDWR|O_CREAT, 0 );
ftruncate( fd , 4);
void* ptr = mmap( NULL, 4, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );
ptr[0] = 100;
munmap(ptr,4);
close( fd );
shm_unlink( 'MapFile' );
見て分かる通り、mmapの引数に入れるファイルディスクリプタを変更するだけです。
Pythonの場合は以下のコードで実装できます。
try:
rt = ctypes.CDLL('librt.so')
except:
rt = ctypes.CDLL('librt.so.1')
m= mmap.mmap(fd, 4, mmap.MAP_SHARED)rt.shm_open.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.c_int]
rt.shm_open.restype = ctypes.c_int
rt.ftruncate.argtypes = [ctypes.c_int, ctypes.c_int]
rt.ftruncate.restype = ctypes.c_int
rt.close.argtypes = [ctypes.c_int]
rt.close.restype = ctypes.c_int
rt.shm_unlink.argtypes = [ctypes.c_char_p]
rt.shm_unlink.restype = ctypes.c_int
O_RDONLY = 0
O_WRONLY = 1
O_RDWR = 2
O_CREAT = 64
fd = rt.shm_open('MapFile',O_RDWR | O_CREAT ,0)
rt.ftruncate(fd, 4)fd = rt.shm_open('MapFile',O_RDWR | O_CREAT ,0)
value = struct.pack("i",100)
m.write(value)
m.close()rt.close( fd )
rt.shm_unlink('MapFile')
PR
この記事にコメントする