メモリマップトファイル

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Cユーザー

メモリマップトファイル

#1

投稿記事 by Cユーザー » 11年前

以下のコードで正しく共有されなくて困っています。
共有メモリに関するDLLを作成し、プロセスAとプロセスBで使用します

コード:

//Samle.dll

long SampleClass::Create()
{
	//共有メモリを作成
	m_handle = CreateFileMapping(
					INVALID_HANDLE_VALUE,
					NULL,
					PAGE_READWRITE,	// 読書き両方にする
					0,
					100,
					"test"// 共有メモリ名を設定
					);

	// マッピング開始
	m_adress = (INFO_DATA *)MapViewOfFile(
					m_handle,
					FILE_MAP_ALL_ACCESS, // 読書き両方
					0,
					0,
					100);

	if(m_adress == NULL)
	{
		return -1;
	}

	m_adress->headerinfo.size = 100;
	m_adress->lineinfo	= (LINE_INFO*)( (DWORD)m_adress +sizeof(HEADER_INFO) );
	return 0;
}

long SampleClass::Open()
{
	m_handle = OpenFileMapping(
					FILE_MAP_ALL_ACCESS, 
					FALSE, 
					 "test");

	if(m_handle == NULL)
	{
		return -1;
	}

	HEADER_INFO* h = (HEADER_INFO *)MapViewOfFile(m_handle,
					FILE_MAP_ALL_ACCESS, // 読書き両方
					0,
					0,
					sizeof(HEADER_INFO));

	// マッピング開始
	m_adress = (INFO_DATA *)MapViewOfFile(m_handle,
					FILE_MAP_ALL_ACCESS, // 読書き両方
					0,
					0,
					h->size);

	if(m_adress == NULL)
	{
		return -1;
	}


	return 0;
}

long SampleClass::Destroy()
{
	if( ( m_adress == NULL ) || ( m_handle == NULL ) )
	{
		return -1;
	}

	//マッピング解除
	UnmapViewOfFile(m_adress);
	//ハンドル閉じ
	CloseHandle(m_handle);
	m_handle = NULL;

	return 0;
}

void SampleClass::Write(char* str)
{
	m_adress->lineinfo->lineNumber = 1;
	strcpy_s(m_adress->lineinfo->strData, str);
}

INFO_DATA* SampleClass::GetData()
{
	return m_adress;
}


順序として

①プロセスAで共有メモリ作成

//プロセスA

SampleClass s;
void CSampleADlg::OnBnClickedButton1()
{
// TODO: ここにコントロール通知ハンドラ コードを追加します。
s.Create();//①
}

②プロセスBで共有メモリオープン
③プロセスBで共有メモリに書き込み
//プロセスB

SampleClass s;
void CSampleBDlg::OnBnClickedButton1()
{
// TODO: ここにコントロール通知ハンドラ コードを追加します。
s.Open();//②
s.Write("hello");//③
}

④プロセスAでデータの確認
void CSampleADlg::OnBnClickedButton2()
{
// TODO: ここにコントロール通知ハンドラ コードを追加します。
INFO_DATA * info = s.GetData();
}

この手順で確認したところ文字列が入っておりませんでした。

何故共有されないのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: メモリマップトファイル

#2

投稿記事 by softya(ソフト屋) » 11年前

共有メモリ上にポインタが有るように見えますが、プロセスごとに論理アドレス空間が違う共有メモリにはポインタは使えませんよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Cユーザー

Re: メモリマップトファイル

#3

投稿記事 by Cユーザー » 11年前

共有メモリにポインタを使っているので共有化されない
ということですか?

Cユーザー

Re: メモリマップトファイル

#4

投稿記事 by Cユーザー » 11年前

先頭アドレスm_adressからsizeof(ヘッダー)分ずらした位置を覚えてるのですが
まずいのかな

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: メモリマップトファイル

#5

投稿記事 by softya(ソフト屋) » 11年前

Windowsなどの仮想記憶の仕組みを理解してもらう必要がありそうです。
「仮想記憶 - Wikipedia」
http://ja.wikipedia.org/wiki/%E4%BB%AE% ... 8%E6%86%B6

プロセスAにとって意味のあるポインタ値でもプロセスBにとっては意味のない不正規なポインタ値となります。
なぜなら前にも書いた通り論理アドレスが違うからです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Cユーザー

Re: メモリマップトファイル

#6

投稿記事 by Cユーザー » 11年前

いやその仮想メモリの話はわかるのですが、それを共有するようにする仕組みがメモリマップトファイルと思ってたのですが・・うーん

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: メモリマップトファイル

#7

投稿記事 by softya(ソフト屋) » 11年前

メモリマップトファイルは、仮想記憶メモリを共有するための仕組みです。
普通のプロセスは、仮想記憶メモリを共有していませんので、お互いの内容は参照できません。

【補足】
プロセスAとプロセスBでマッピングされている論理アドレスが違うはずです。
プロセスAで0x200000だったとして、プロセスBで0x210000だとします。
プロセスAで0x200010と言う値のポインタ値をつくってマッピングされたメモリに書き込んだとしましょう。
それをプロセスBで参照すると0x200010は割り当てられていないメモリですからエラーになるでしょうって事です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Cユーザー

Re: メモリマップトファイル

#8

投稿記事 by Cユーザー » 11年前

なんとなくわかります。

ただちょっと一番私の理解のネックになっているのが
ポインタであればNGとのことなのでポインタの場合は先ほど説明していただいた理由でエラーになる

ポインタでなければどういう仕組みでマッピングされるのでしょうか。
そこのポインタである場合とポインタでない場合のメモリマッピングの違いがイマイチぴんときません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: メモリマップトファイル

#9

投稿記事 by softya(ソフト屋) » 11年前

Cユーザー さんが書きました:なんとなくわかります。

ただちょっと一番私の理解のネックになっているのが
ポインタであればNGとのことなのでポインタの場合は先ほど説明していただいた理由でエラーになる

ポインタでなければどういう仕組みでマッピングされるのでしょうか。
そこのポインタである場合とポインタでない場合のメモリマッピングの違いがイマイチぴんときません。
よく分かっておられない様なので、デバッガでプロセスAとプロセスBの次のポインタ値を調べて書きだして下さい。
そして書きだしたアドレスを見て考察してみて下さい。

m_adress
&(m_adress->lineinfo)
&(m_adress->lineinfo->lineNumber)
&(m_adress->lineinfo->strData)
m_adress->lineinfo->strData
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

YuO
記事: 947
登録日時: 13年前
住所: 東京都世田谷区

Re: メモリマップトファイル

#10

投稿記事 by YuO » 11年前

Cユーザー さんが書きました:いやその仮想メモリの話はわかるのですが、それを共有するようにする仕組みがメモリマップトファイルと思ってたのですが・・うーん
softya(ソフト屋) さんが書きました:メモリマップトファイルは、仮想記憶メモリを共有するための仕組みです。
Memory mapped fileはファイル (の一部) をメモリ空間に擬似的に割り付けて,ポインタでのファイルアクセスを可能にするための仕組み,です。

なんで,「file」という言葉があるのにファイルを扱うための仕組みが本質であることを無視するかなぁ,と思ったり。
元々ファイルへのアクセスなので,論理アドレスがプロセス毎に異なっても当然だし,ポインタを含めることが実質的にできないのも当然なのですが……。
# 後者はファイルにポインタ値を出力して,それを別のプロセスで利用するのか?という話。
Cユーザー さんが書きました:ポインタでなければどういう仕組みでマッピングされるのでしょうか。
そこのポインタである場合とポインタでない場合のメモリマッピングの違いがイマイチぴんときません。
構造体等にポインタがあろうが無かろうが,仕組みは変わりません。
そのメモリの情報をプログラムがどう認識するかは,プログラムに任されています。
  • 「ファイル」 or 「物理メモリ」 or 「物理メモリからページアウトされたデータ」はプロセス間で共有される
  • 上記をプロセスのメモリ空間に割り付ける「ページング情報」は,プロセス毎に異なる
  • 「ページング情報」が異なるため,一番上の「データ」が割り付けられる「論理アドレス」はプロセス毎に異なる
というのが,前提となる知識で,その上で,
  • Windows (に限らず,x86/x64上の大抵のOS) では,セグメント・セレクタは実質機能しておらず,コンパイラは「ポインタの値」を「論理アドレス」そのまま使用している
  • 先に記述した通り,「論理アドレス」はプロセス毎に異なる
  • よって,「ポインタの値」をプロセスを越えて共有しても意味がない
というのが,共有メモリ中でポインタが使えない理由です。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: メモリマップトファイル

#11

投稿記事 by softya(ソフト屋) » 11年前

前に書き添えたのですが忘れられたので、もう一度書いておきます。
「メモリマップトファイル • C言語交流フォーラム ~ mixC++ ~ バイナリファイルで別プログラムにデータを受け渡すプログラムを書いて見ることをオススメします」
http://dixq.net/forum/viewtopic.php?t=1 ... 871#p99878
バイナリファイルでプログラム間でデータを受け渡せない技術力ではメモリ共有など早すぎます。

あと、SampleClassってプロセス同期の仕組みが入っていないんですが別にやってますよね?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Cユーザー

Re: メモリマップトファイル

#12

投稿記事 by Cユーザー » 11年前

すいません、ありがとうございました

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: メモリマップトファイル

#13

投稿記事 by softya(ソフト屋) » 11年前

Cユーザー さんが書きました:すいません、ありがとうございました
この間から堂々めぐりしてますので、ここで締め切らず理解できるまでやってはどうでしょうか?
また同じ事を繰り返すと思いますので、この機会にちゃんと理解されたほうが良いとおもいます。

それと解決コードを提示されていないので、フォーラムルール義務違反でもあります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る