• ベストアンサー

メモリマップドファイルは動作原理的に…

QueryPerformanceCounterを使ってそれほど複雑でない関数でのベンチマークを行ったところ 今のところ全ての場合においてメモリマップドファイルのほうが単純なファイルの読み書きより高速でした。 (こんないい機能があったなんて…(笑)) それほど差がない場合もありましたが、場合によっては100倍以上もの差になった時もあります。(実メモリと比較したら全然ではありますが) メモリに困ることは最近それほどなかったので、、仮想メモリのスワップアウトが起きるとどれくらいの速度で動作することになるのか 全く実感できなかったのですが 1.このメモリマップドファイルは 原理的に、それを明示的に行うようなものとみなして問題ないでしょうか? 2.書き込み可能な属性で作り CreateFileMappingに指定するサイズがファイルサイズより大きかった場合はファイルが拡張され、それ以下だった場合はそのままのようです。 しかし、実際にそれ未満の数値を指定して、その指定したサイズ以上のアドレスのところへ書き込もうとすると、メモリの場合サクッと不正終了してくれるので逆におかしいところがあることが分かるので安心できるともいえるのですが、こちらはファイルサイズに余裕があれば、指定したサイズを超えた部分へもどうやら書き換えることができてしまうようです。 この場合、もしファイルサイズすら超えた数値へ間違って書き込み命令を出してしまった場合、切り捨てられるのでしょうか?それともどこか別のところが書き換えられてしまう危険があるのでしょうか? 3.また、試したら出来てしまったのですが 別のポインタを使って操作するのは「通常の動作」でしょうか? それとも未定義の動作でしょうか? 例) ・ ・ ・ char *a = (char*)MapViewOfFile( hMap, FILE_MAP_WRITE , 0, 0, 0); wsprintf(a,"aaaaaa"); char *b= a+3; wsprintf(b,"bbbbbb"); b+=3; wsprintf(b,"ccc"); UnmapViewOfFile( a ); ・ ・ ・ 結果: aaabbbccc

質問者が選んだベストアンサー

  • ベストアンサー
  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.3

えーと、質問ではMapViewOfFileでマッピングサイズに0を指定していますが、この場合はマッピングオブジェクト全体がアドレス空間にマップされます。CreateFileMappingとファイルもサイズ0だとエラーになりますので、マッピングオブジェクトはある程度の大きさを持っているはずです。質問の例は意図せずファイル範囲内になっている可能性があります。 あとマップサイズがページサイズ(4KB)の倍数でない場合、端数分は範囲を超えてもアクセス例外は出ないでしょう。また範囲を超えたらアクセス例外が起きることに期待するのは間違いです。そのアドレスにたまたま何か有効な変数に割り当てられているとアクセス例外にはなりませんから。 マップした範囲内なら反映までにある程度の遅延はあるにしてもファイルに反映されます。範囲外だとアクセス例外が出るか、何も出ずに書き込めてしまうかは分かりません。書き込めてもファイルには反映されないと思いますが、無関係な変数を壊している可能性はあります。 4.通常の動作としてはファイルを指定していればそのファイルをマップするのでスワップファイルへのマップはないと思いますが、仕様に明記されていないので保証はできません。

LongSecret
質問者

お礼

ありがとうございます。 MapViewOfFileについては、上記コードは不正終了しなかった一例として書いただけですので、実際には色々と実験していました。 …が、4KBの倍数にしてはいませんでした。 実際に4KBにしてそれを超えたところへ書き込もうとしてみると、見事に「不正終了」してくれました! また >範囲を超えたらアクセス例外が起きることに期待するのは間違い というのを確認できれば十分です。 一見必要そうな状況があった場合に、そのために変数を用意する必要が本当にあるかどうかが一番の気がかりだったわけですが 通常のメモリと同じように書き込み範囲のサイズを保存しておく方が万全ならば、その変数を「別の場所でも活用した」処理をさせることを考えられれば、パフォーマンス上も全然十分だと思います。 4についても、イメージ通りのようで、安心しました。 これで安心して先に進めそうです。

その他の回答 (2)

  • hidebun
  • ベストアンサー率50% (92/181)
回答No.2

#1さんの1.→FlushViewOfFileかと。

LongSecret
質問者

お礼

ありがとうございます。 リモートコンピュータではFlushViewOfFileを普通に呼んでも同期が保証されないようですが 私の目的はローカルコンピュータなのでそれで同期が保証されるようですね。 もちろん >CreateFile 関数を使ってファイルを開く際に FILE_FLAG_WRITE_THROUGH フラグを指定すると、物理的な書き込みが完了した後で FlushViewOfFile が制御を返すようになります。 とMSDNに書いてあるので、リモートでやりたいならそうすればOKですね。

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.1

1. メモリマップドファイルは、プロセスのアドレス範囲を利用できるようにする機能です。同時にそのアドレス範囲のスワップアウト先を指定ファイルにすることができます。 なお、マップしたメモリへの書き込みは必ずしも即座にファイルに反映されるわけではないので注意してください。ファイルでもフラッシュが必要なように、同期APIの呼び出しが必要です。 # 同期APIの名称を思い出せない。アンマップ時しか同期できないかも 2. 書き込み可能マップを作ると、書き込みの有無に関わらずファイルはそのサイズまで拡大されます。逆にマップ作成時に指定したサイズを超えてのアクセスはアクセス例外になります。 3. メモリマップドファイルは、プロセスの指定アドレス範囲を利用可能にします。プロセスで利用可能なアドレス空間をプロセス内のどのポインタでアクセスしても有効です。

LongSecret
質問者

お礼

ありがとうございます。 やはり明示的に同期させなければ同期が保証されないという点以外は、メモリと同じような扱い方が出来るようですね。 しかし、2のアクセス例外というのは、OSが勝手に握りつぶしてくれる(ファイルのサイズ内なら普通どおりやり、その外だとやめてくれる…?) のでしょうか? 上記のとおりファイル範囲外に代入したようなコードでも不正終了など全く起こらないばかりか、GetLastErrorとか使っても何も捕捉できません。 使用を控えていた try catch で念のため実験(catchは(...)で)してみても、やはり何も例外を受け取りません。 すみません(汗 もうひとつ重大なことを忘れていました。 4.0xFFFFFFFFを指定するとページングファイルを使うことになり それ以外なら普通のファイルを使うことになり、ページングファイルは全く使用しないことが保証されるのでしょうか?

関連するQ&A

  • MapViewOfFile() はカウンタを進めない?

    Windows APIの質問です。 PINT GetShareInt() { ____HANDLE hmap = CreateFileMapping( ________INVALID_HANDLE_VALUE, NULL, ________PAGE_READWRITE, ________0, sizeof(int), ________TEXT("Share") ); ____PINT pi = (PINT)MapViewOfFile( ________hmap, FILE_MAP_WRITE, 0, 0, 0); ____CloseHandle(hmap); ____return pi; } こんな感じの関数で変数をプロセス間共有したいのですが、 ファイルマッピングオブジェクトが毎回生成されてしまい、 変数を共有できません。 先にCloseHandleするのは後の処理がUnmapViewOfFileするだけで すむからです。変則的ですが、MapViewOfFile呼び出ししている以上 hmapが指すカーネルオブジェクトは開放されないと思うのですが。 MapViewOfFileがカーネルオブジェクトの内部カウンタを進めていない、 ということでしょうか?それではマルチスレッドで扱えないような気が するのですが、私の認識のどこが間違っているのでしょうか? よろしくご指導お願い申し上げます。

  • 漏電ブレーカーの動作原理について

    電源から漏電ブレーカーを2つ(電源側をA、負荷側をBとします)介して負荷につながる電路があります。 負荷の不良で漏電が生じた時にブレーカーAばかりが動作します。 Q1:仮にブレーカーAとBを同じ物とした場合に漏電でAばかりが動作するのはどういう理屈でしょうか? 電路の長さが関係しているのでしょうか? Q2:ブレーカーA、B間、負荷との長さを同一、ブレーカーAとBの漏電遮断動作電流も同一としてブレーカーA、Bの容量が異なる場合、Aばかりが動作する要因になりうるか? それはどんな場合か?

  • この動作のコードを教えてください。ExcelVBA

    以下の動作をするためのコードを教えてください。 ExcelVBAでお願いします。 フォルダ1、2に入っているファイルが以下のようになっていた場合 フォルダ1 A.xlsx,B.xlsx,C.xlsx フォルダ2 A.xlsx,C.xlsx,E.xlsx B.xlsxはフォルダ2に存在しない E.xlsxはフォルダ1に存在しない とmsgboxを出したい。 ヒント:フォルダ1を指定したときにフォルダ内にあるExcelのファイル名を配列にいれる処理が必要

  • Photoshopの出力設定

    PhotoshopのCS5を使っています。 新規ファイル作成時に幅と長さをA4のサイズに指定しています。 カンバスサイズもA4のサイズになっています。 プリントダイアログの左側プレビュー欄上部の数値がどうしてもA4サイズになりません。 これが原因だと思うのですがプリントもサイズ通りに出力されません。 ここの数値を設定したい数値にする場合はどのようにしたらいいでしょうか? 他のサイズで試しても同じような状況です。 教えて下さいよろしくお願い致します。

  • メモリ確保エラー時の効率的な書き方

    mallocなどで複数の変数に対してメモリを確保する場合があると思います.例えば3つの変数の場合, char *a, *b, *c; a = (char *)malloc(100); if(a==NULL){ /* メモリ確保できなかったとき */ return (-1); } b = (char *)malloc(100); if(b==NULL){ free(a); return (-1); } c = (char *)malloc(100); if(c==NULL){ free(a); free(b); return (-1); } 変数が多くなるにつれて後から確保する変数のエラー処理(すでに確保したメモリのfree)が増えてしまうので,何か良い方法(コードが短くなるような)はないでしょうか?

  • fwrite(3)の第2,第3引数の使い方

    man fwrite(3) を見ると、宣言は以下のようになっています。 size_t fwrite(const void *BUF, size_t SIZE, size_t COUNT, FILE *FP); 「BUF から、1つあたり SIZE byte を COUNT 個 FP に書き込む」という関数だと思うのですが、SIZE と COUNT 値はどう指定したらよいのでしょうか? たとえば、char BUF[1024] で全部書き込みたい場合に、SIZE = 1, COUNT = 1024 と指定するのと、SIZE = 4, COUNT = 256 と指定するのでは、書き込み速度や結果に違いが出るのでしょうか?

  • ブラウザによりフォントサイズが異なってしまう問題をCSSで解決する原理

    ブラウザによりフォントサイズが異なってしまう問題をCSSで解決する原理と方法は? 例えばIEではちょうどよいサイズ(作成者が10ptを指定してその通りのサイズ)で表示されているのが、FireFoxでは小さく表示されてしまうという問題は、CSSを使えば解決できるそうですが、それはどのような原理で解決できるのでしょうか。また、どのような設定をすればよいのでしょうか。 私はCSSファイルの役目は指定箇所(クラス)を指定フォント/サイズで表示するよう指示するもの、という程度のことは分かっていますが、HTMLファイル上で直接10ptと指定するのと、CSSで10ptと指定するのではどう違うのか。または、数値ではなくて相対的なサイズを指定する必要があるのでしょうか? その辺の原理が分かっていませんので、ごく簡潔に教えていただけるとありがたいです。 また、分かりやすいサイトも教えていただければありがたいです。

  • [C#][FX]DLLを利用した共有メモリの動作

    こんにちわ。 外国為替取引のFXに利用するプログラムを作成しています。 その中で、 C#のプログラムAと MQLという言語によるプログラムBにおいて、 共有メモリ読み書きを行うDLLを利用して、 (1)Aの結果を共有メモリに書き込み→Bで受け取って処理。 (2)Bの結果を共有メモリに書き込み→Aで受け取って処理。 という仕組みを作成しています。 (2)はできたのですが、(1)がうまくいきません。 知見をお持ちの方アドバイスいただけませんでしょうか。 以下詳細でございます。 ●相談内容 共有メモリ書き込み時に以下エラーが発生し、書き込みができない。 「保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。」 ●ソース(一部抜粋。InitializeとRunは基盤システムからコールされます。) 【C#ソース】 using System.Runtime.InteropServices; using System; [DllImport("MemMap.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern string SetMemString(string tag, string msg); public bool Initialize() { try{ Console.Write("try01"); SetMemString("TEST", "1"); Console.Write("try02"); SetMemMethod(); }catch(Exception e){ Console.Write(e.Message); Console.Write(e.StackTrace); } return true; } public void SetMemMethod(){ SetMemString("TEST", "2"); } public void Run(){ try{ Console.Write("try03"); SetMemString("TEST", "3"); }catch(Exception e){ Console.Write(e.Message); Console.Write(e.StackTrace); } } } } 【コンソール】 try01 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。 場所 test.Main.SetMemString(String tag, String msg) 場所 test.Main.Initialize() try03 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。 場所 test.Main.SetMemString(String tag, String msg) 場所 test.Main.Run( 【DLL】 MT4_EXPFUNC const char* __stdcall SetMemString(char *tag,char *msg) { /*static*/ string ret = ""; bool create = false; HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, tag); if (!hMap) { hMap= CreateFileMapping((HANDLE)0xFFFFFFFF , NULL , PAGE_READWRITE , 0 , 1024 , tag); q.push(hMap); create = true; } LPSTR strAllCmd =(LPSTR)MapViewOfFile(hMap , FILE_MAP_WRITE , 0 , 0 , 0); lstrcpy(strAllCmd , msg); FlushViewOfFile(strAllCmd,0); UnmapViewOfFile(strAllCmd); if(!create) CloseHandle(hMap); return(ret.c_str()); } ●詳細 try01直後の初期化メソッド(Initialize)で直接コールするSetMemStringは問題なく出来ており、プログラムB側で読むことができていますが、 try02直後の初期化メソッド(Initialize)でコールするメソッドの中のSetMemStringと try03直後のメイン処理(Run)の中のSetMemString でエラーが発生します。 try02はソースの綺麗さを保つために別メソッドに切り出したいだけなので、 最悪初期化メソッドに直書きすればよいですが、 メイン処理なので、try03でエラーが発生するのはなんとしても解決したいです。 try01で呼べていることからDllImportのスコープがうまくできていないのでは? と考えています。 継承元のExpertクラスはソースが隠蔽されていて、わかりませんが、 何かアドバイスいただけませんでしょうか。よろしくお願いします。

  • PHP動作の仕組み

    初心者ですが、PHP動作時のメモリの仕組みを教えてください。 (1)Aさんがサーバにアクセスした時、PHPはデータを読み込みますが、メモリはいつのタイミングで破棄されるのでしょうか (2)例えば1GBのファイルだと読み込みに時間かかるので、サーバ起動時に事前にメモリに読み込んでおくことはできますか (3)AさんBさんがサーバにアクセスした時、PHPはデータを読み込みますが、一回分を読み込むんでしょうか、それとも 二人分を読み込むでしょうか。 目的はギガ単位のファイル数個のみを大人数にリアルタイムに閲覧したいのですが、あいにく初心者の上、自宅にテスト環境もありません。詳しい方お願いします。

    • ベストアンサー
    • PHP
  • Officeの動作が遅い

    いつもお世話になっております。 Office の動作が非常に遅く、困っております。 (よく使用するExcel、Word) ファイルサイズは1MBもなく、シート数も2~3ページのものがほとんどです。 フォントを変更しようと右クリック>セルの書式設定を開くと フリーズしてしまったり、罫線を引くのにとても時間がかかったりします。 その間にファイルの操作等すれば、応答なしになり強制終了してしまいます。 1)再インストールはやってみましたが、解決しませんでした。 2)アプリケーションの自動修復をやったのですが、解決しませんでした。 3)↓のサイトに書いてあることもやってみましたが、解決しませんでした。   http://turedure.cocolog-nifty.com/log/2007/08/post_b90b.html 応答なしになった場合、CPUの使用率が高くなる訳ではありません。 メモリは2GBあるので、問題はないと思います。 何かほかに方法はございますでしょうか。 よろしくお願いいたします。 <バージョン>  Office 2000