Boost(3)メモリマップを使ってみる
概要 :
今回の記事は、メモリマップ(共有メモリ(Shared Memory))をBoostで使ってみます。
メモリマップは、WIndowsでは、APIが用意されていますので、結構、使われています。そのメモリマップと同じ動作をするようにBoostでは、どのように記述すれば良いか、簡単に記述したいと思います。
では、早速、サンプルソースを使って試してみましょう。
ここで使用するプログラムは、Boostのサンプルソースを判りやすく、一部、変更したものです。
オリジナルのサンプルソース :
ここで使用したサンプルソースコード:
コンソールアプリケーションで試してみましょう
簡単に動作確認するために、上記のオリジナルサンプルを、少しだけ、わかりやすいように変更してみました。
では、早速、ソースコードを見てみましょう。
[sample.cpp]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
| #include <iostream>
#include <string>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <cstdlib> //std::system
#include <sstream>
using namespace std;
using namespace boost;
using namespace boost::interprocess;
// const data
const char * MMMAP_NAME = "MySharedMemory";
int max_share_size = 65536;
int real_share_size = 1024;
int main (int argc, char *argv[])
{
if(argc == 1){
shared_memory_object::remove(MMMAP_NAME);
// Create a managed shared memory segment
managed_shared_memory segment(create_only, MMMAP_NAME, max_share_size);
// Allocate a portion of the segment (raw memory)
std::size_t free_memory = segment.get_free_memory();
void * shptr = segment.allocate(real_share_size);
// Check invariant
if(free_memory > segment.get_free_memory()){
char *pbuff=(char *)shptr;
pbuff[0]='A';
pbuff[1]='B';
pbuff[2]='C';
pbuff[3]=NULL;
// convert memory to handle
managed_shared_memory::handle_t handle = segment.get_handle_from_address(shptr);
// set of child process param .
std::stringstream s;
s << argv[0] << " " << handle;
s << std::ends;
cout << "handle:" << handle << endl;
// Launch child process
int nchild = std::system(s.str().c_str());
cout << "child return:" << nchild << endl;
cout << "changed?:"<< pbuff << endl;
// delete share memory
segment.deallocate(pbuff);
string sdata;
cin >> sdata ; // any key input!! --> exit.
// delete share memory
shared_memory_object::remove(MMMAP_NAME);
} else {
// delete share memory
shared_memory_object::remove(MMMAP_NAME);
return 1;
}
} else {
//Open managed segment
managed_shared_memory segment(open_only, MMMAP_NAME);
//An handle from the base address can identify any byte of the shared
//memory segment even if it is mapped in different base addresses
managed_shared_memory::handle_t handle = 0;
//Obtain handle value
std::stringstream s; s << argv[1]; s >> handle;
// Get buffer local address from handle
void *msg = segment.get_address_from_handle(handle);
char *pbuff=(char *)msg;
cout << "origin:" << pbuff << endl;
// change data!!
pbuff[0]='D';
pbuff[1]='E';
pbuff[2]='F';
pbuff[3]=NULL;
}
return 0;
}
|
このプログラムは、引数なしで起動すると、自動的に子プロセス(同じプログラム:引数にハンドル番号が指定される)を起動して
メモリマップの情報が、両方のプロセスで読み書きできるかを試したものです。
では、簡単に解説をしてみます。
19行目は、メモリマップに同じ名前を使用できないので、その名前のメモリマップがあれば、削除しています。
21行目は、メモリマップを新規に作成しています。引数には、名前と最大メモリサイズを指定します。
24行目は、作成したメモリマップの空きメモリサイズを確認しています。
25行目は、作成したメモリマップで、本当に使う領域を確保しています。
28行目は、作成したメモリマップで、本当に使う領域をと空き領域の差を確認しています。
空き領域より、本当に使う領域が大きくなってしまっている場合は、異常と判断しています。
30行目からは、メモリマップの領域に情報を書き込んでいます。
37行目は、子プロセスへ情報を渡すためのハンドル情報を取得しています。
44行目は、子プロセスを起動しています。
66行目からが、子プロセスの処理です。
ここでは、メモリマップを開いて、引数でもらったハンドルから、領域のアドレスを取得しています。(76行目まで)
80行目で、実際の中身を出力して、情報が読めているか確認します。
83行目からは、今度は、書き込みをしています。
親プロセスは、47行目で、変更された情報が読めるか確認しています。
実際に、実行してみると、以下がその実行結果が表示されます。
1
2
3
4
| handle:96
origin:ABC
child return:0
changed?:DEF
|
思ったとおりに、読み書きができました。
Boostでは、このように、メモリを認識するためにハンドル情報を使います。
ハンドル情報の受け渡しが必要になってしまうのでは、他プロセス間通信を行うのには、少々不便ですね。
Windowsのメモリマップのように固定文字列のみで、読み書きできようにするためには、どうするのでしょう。
ちゃんと、それも用意されています。Boostでは、オブジェクトでのやり取りをするように設計されています。
25行目を、以下のように、変更します。
1
| MyClass *myclass = segment.construct<MyClass>("MyClassObject")();
|
また、取り出すときは、76行目を以下のような感じで変更すると、該当オブジェクトのアドレスを取得できます。
1
2
| std::pair<CMemMappedData*, std::size_t> res=segment.find<CMemMappedData>("MyClassObject");
MyClass *myclass = res.first;
|
ここで使うMyClassは、独自に作成することができますが、そのクラスでは、new や mallocなどをやってメモリ確保をしても
共有できないので、注意が必要です。
メモリを動的に確保したい場合は、先の例のように、managed_shared_memoryのallocateを使い、ハンドル情報を属性に持たせて共有すれば良いでしょう。
もっと、Boostについて詳しく知りたい方は、以下の本なども良いと思います。
本から学ぶことは多いと思います。ネットだけでは判らない様々な事に気づかされます。
コメントをどうぞ