- PR -

SharedMemoryの排他制御について

投稿者投稿内容
WT
常連さん
会議室デビュー日: 2004/07/22
投稿数: 29
投稿日時: 2007-03-21 14:33
VC++7(VS-2003)にてSharedMemoryの機能を使っています。
SharedMemoryといっているのは
  OpenFileMapping()
  CreateFileMapping()
  MapViewOfFile()
等のAPIを使用してWindowsのページングファイル内にメモリ上の情報を読み書きする機能と認識しています。
このSharedMemoryはDLLで提供される予定です。
DLLは複数のexeから呼出され、読み書きされます。
当然、排他制御のような機能が必要となると考えています。

実際に排他制御を実現するにはどのような手法があるのでしょうか?
自分が今、考えているのはMutexを使って排他制御するやり方です。

SharedMemory-DLL内のAPIがコールされる度に、関数内でMutexを作成、チェックし、一度に一つのexeしか処理できないようにしたいと考えています。

このやり方は一般的でしょうか?
又、自分の中で
  SharedMemory-DLL内でMutextを使用するのではなく、SharedMemory-DLLを
  呼出すほうのexe内でMutexを使って制御すべきなのか?
と、言う軽い疑問もあったりします。

どなたか、経験の有る方等、アドバイスいただきたいです。
宜しくお願いします。
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2007-03-21 17:44
引用:

WTさんの書き込み (2007-03-21 14:33) より:
SharedMemoryといっているのは
  OpenFileMapping()
  CreateFileMapping()
  MapViewOfFile()
等のAPIを使用してWindowsのページングファイル内にメモリ上の情報を読み書きする機能と認識しています。



Windowsでページングファイルというと、
Swapファイルと解釈してしまう気がします。

ファイルマッピングは、通常のファイルを仮想メモリにマッピングして、
メモリの読み書きでファイルを扱えるようにするためのものです。

その辺りの仕組みを応用して、実ファイルのないマッピングを
共有メモリとしても扱えるという方が正確なのではないでしょうか。

引用:

SharedMemory-DLL内のAPIがコールされる度に、関数内でMutexを作成、チェックし、一度に一つのexeしか処理できないようにしたいと考えています。

このやり方は一般的でしょうか?



DLL内のAPIがコールされる度にMutexを生成したのでは、
異なるMutexとなるので排他制御の意味がないのでは?

複数プロセスから使う場合は、名前付き、もしくは、
親プロセスから継承させる方法のどちらかだったと思います。

「作成」が名前付きMutexの「Create/Open」の意味なら問題ありません。

引用:

又、自分の中で
  SharedMemory-DLL内でMutextを使用するのではなく、SharedMemory-DLLを
  呼出すほうのexe内でMutexを使って制御すべきなのか?
と、言う軽い疑問もあったりします。



設計にもよるとは思いますが、
共有メモリをDLLの外部に仕様として公開するのですか?

一般的にはプロセス間通信の詳細として隠蔽すると思います。
DLLの外部にはもっと高水準のAPIを提供するものですよね。

性能要件などの理由もあるので一概には言えませんが、
これらの制御をDLLの外部で行うべきではないと思います。
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2007-03-21 17:47
こんにちは。

引用:

WTさんの書き込み (2007-03-21 14:33) より:
実際に排他制御を実現するにはどのような手法があるのでしょうか?
自分が今、考えているのはMutexを使って排他制御するやり方です。



Mutexでよいと思います。

引用:

又、自分の中で
  SharedMemory-DLL内でMutextを使用するのではなく、SharedMemory-DLLを
  呼出すほうのexe内でMutexを使って制御すべきなのか?
と、言う軽い疑問もあったりします。



私ならこっちです。共有メモリの機能と排他制御の機能は別々に提供して欲しいです。
例えば、
 1.共有メモリのデータを読み込み
 2.データの一部を変更
 3.共有メモリへデータを書き戻し
を想定した場合、1〜3の一連の処理の間でロックを掛けたいので。

引用:

どなたか、経験の有る方等、アドバイスいただきたいです。



FileMapping(共有メモリ)とMutexの組み合わせは実際の開発で経験ありますね。
いちいち覚えていないのですが少なくとも2つ以上の開発で使いました。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-03-21 18:17
引用:

Windowsでページングファイルというと、
Swapファイルと解釈してしまう気がします。



ファイルマッピングは、ユーザファイルだけではなく、オプションでページファイル上の領域を使用することも出来ますよ。

引用:

ファイルマッピングは、通常のファイルを仮想メモリにマッピングして、
メモリの読み書きでファイルを扱えるようにするためのものです。



この表現は微妙ですね。

ファイルマッピングの主目的は(結果として行われる)ファイル更新ではなく、ページファイル、あるいはユーザファイルを足がかりとした比較的大規模のメモリ共有によるプロセス間通信の実現にあります。

引用:

その辺りの仕組みを応用して、実ファイルのないマッピングを
共有メモリとしても扱えるという方が正確なのではないでしょうか。



「実ファイルがない(=ページファイルを利用したファイルマッピング)」のことを指しているのかもしれませんが、ファイルマッピングはその仕組み上実ファイルが必須です。
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2007-03-21 18:57
引用:

渋木宏明(ひどり)さんの書き込み (2007-03-21 18:17) より:
ファイルマッピングの主目的は(結果として行われる)ファイル更新ではなく、ページファイル、あるいはユーザファイルを足がかりとした比較的大規模のメモリ共有によるプロセス間通信の実現にあります。



単に順番として、
1. ファイルI/Oをメモリにマッピングする
2. 同一ファイルのマッピングを同一物理ページに割り当てる
3. その結果、プロセス間で共有メモリを扱うことが可能になる
という方向の説明をしただけです。

が、確かに表現としてはよくないですね。

引用:

「実ファイルがない(=ページファイルを利用したファイルマッピング)」のことを指しているのかもしれませんが、ファイルマッピングはその仕組み上実ファイルが必須です。



最終的にページファイルは利用される可能性は高いでしょう。
Unix系のmmapではAPIの仕様上、ファイルが必須となります。

ただ、Windowsでは、システムにページファイルなし、
かつ、マッピング先のファイルを指定しない状態でも、
マッピングの名前による共有も可能だったと思うのですが。

こちらの場合はSysV IPCの共有メモリのイメージに近いと思います。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-03-22 09:02
引用:

ただ、Windowsでは、システムにページファイルなし、
かつ、マッピング先のファイルを指定しない状態でも、
マッピングの名前による共有も可能だったと思うのですが。



CreateFileMapping() のヘルプには、CreateFileMapping() に INVALID_HANDLE_VALUE を渡した時はページファイル上に領域確保が試みられる、と記載されています。

ページファイルを使わないようにOS設定を構成した場合にどう振舞うかは、記載がないので分かりません。
実メモリが十分にあれば、メモリだけでも動作するような気はしますね。


WT
常連さん
会議室デビュー日: 2004/07/22
投稿数: 29
投稿日時: 2007-03-22 11:45
皆様、アドバイスありがとうございます。
既に渋木さんから指摘あるように、Windowsのページファイルを使ったファイルマッピングを使用したいと考えていました。

今回は確実に仮想メモリ=0(なし)の環境ではないので、ページファイルを利用する事に問題はないかと思っていました。
ただ、今回作成するプログラム類が異常終了した時にページファイル上にゴミが残ってしまう点だけは危惧しておりますが・・・


(話を戻して・・)mutexを使った排他制御が一般的である(まぁ、普通)事を聞き、mutexを使用しての排他制御を実装したい。と、考えました。
その上で気になるのが、あしゅさんの・・・

>DLL内のAPIがコールされる度にMutexを生成したのでは、
>異なるMutexとなるので排他制御の意味がないのでは?
>
>複数プロセスから使う場合は、名前付き、もしくは、
>親プロセスから継承させる方法のどちらかだったと思います。
>
>「作成」が名前付きMutexの「Create/Open」の意味なら問題ありません。

と、言うくだりです。
今の私の考えだと・・・

DLL内で
  writeSharedMemory()
  readSharedMemory()
を定義し、各exeは上記APIを使用します。
各APIの中でmutexを生成、チェックするのですが、ここで言うmutextの生成とは
  Mutext(FALSE,"MyMutex")
のように名前付きMutexの作成を意味しています。
チェックとは
  OpenExisting("MyMutex")
を行う事を意味しています。

DLL内で唯一の名前を定義し(上記で言えば"MyMutex")、その名前を使ってMutexを作成、チェックすれば、複数のexe間でも、唯一のMutexしか使用しない。と、思っていたのですがこの認識は誤りでしょうか?


説明がふがいないのですが、宜しくアドバイスお願いします。
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2007-03-22 12:46
Mutext(FALSE,"MyMutex") や OpenExisting("MyMutex") が何しているのか分かりませんが、チェックなどしなくても、名前付き Mutex を作る際にまだ Mumtex が存在しなければ作るし、既に存在すれば作成済みの Mutex のハンドルを返しますよね。
_________________
囚人のジレンマな日々

スキルアップ/キャリアアップ(JOB@IT)