レガシー Windows API(概要)について

ここで紹介しているAPIは、Windows95、Windows NT3.5時代のAPI群であり、最新のAPIは含まれていないことに注しして欲しい。なお、当時の解説書は現在よりもより詳細に解説しているため、参考になるはずである。

  • レイアウトを変換する際、崩れているページがあります。
  • 概要およびSampleコードはありますが、APIの解説はありません。

ご要望があれば旧版のWin32 API(HELP形式)をお譲りします。問い合わせフォームより申し込みください。

Windows API ファイル マッピングの概要

「ファイル マッピング」とは、 ファイルの内容をプロセスの仮想アドレス空間にコピーすることです。ファイルの内容のコピーは「ファイル ビュー」と呼ばれ、 オペレーティング システムがコピーを管理するために使う内部構造体は「ファイル マッピング オブジェクト」と呼ばれます。

あるプロセスのファイル マッピング オブジェクトを使って、 別のプロセスが自分自身の仮想アドレス空間に等価なファイル ビューを作成できます。これによって、 複数のプロセスがデータを共有できます。ファイル マッピング オブジェクトの名前またはハンドルを持つプロセスは、 ファイル ビューを作成できます。

Microsoft(R) Windows NT(TM) のファイル マッピング関数は、 このようなデータ共有方法に必要なファイル マッピング オブジェクトやファイル ビューを作成します。

ファイルの共有

メモリ ブロックの共有

ファイル ビューのクローズ

ファイル マッピングの使用

ファイル マッピング関数

ファイルの共有

複数のプロセスが1つのファイルを共有しなければならない場合、 いずれかのプロセスがCreateFile関数を使ってファイルを排他アクセス用にオープンしなければなりません。CreateFileMapping関数は、 CreateFileが返したハンドルを使って、 ファイル マッピング オブジェクトを作成します。ファイル マッピング オブジェクトの名前またはハンドルを持つプロセスは、 ファイルのデータを共有できます。ファイル ハンドルは、 プロセス間でのファイルの共有が不要になるまでオープンしたままにしておいてください。これによって、 非共有プロセスからはファイルの読み書きができなくなります。

CreateFileMappingによって、 オブジェクト名、 ファイルからマップするバイト数、 マップされたメモリへの読み書きアクセスを指定できます。CreateFileでファイルをオープンしたときのアクセス フラグと指定されたアクセス フラグが矛盾する場合、 CreateFileMappingは失敗します。CreateFileMappingは、 ファイル マッピング オブジェクトのハンドルを返します。このハンドルは、 プロセスの仮想アドレス空間にファイルの覗き窓 (「ファイル ビュー」) を作成するのに使われます。ファイル ビューは、 要求されたバイト数に応じて、 ファイル全体またはファイルの一部のコピーになります。

ファイル マッピング オブジェクトを作成したプロセスは、 MapViewOfFile関数にファイル マッピング オブジェクト ハンドルを指定して、 ファイル ビュー (ファイルのコピー) をプロセスの仮想アドレス空間に作成できます。MapViewOfFileは、 ファイル ビューを指すポインタを返します。CreateFileMappingでマッピング オブジェクトを作成したときのアクセス フラグと指定されたアクセスフラグが矛盾するときは、 この関数は失敗します。

ファイル ビューのデータを共有するには、 ほかのプロセスは同等なファイル ビューを自分自身の仮想アドレス空間に作成しなければなりません。この作業を行うには、 プロセスは、 同じファイル マッピング オブジェクトのハンドルを取得してから、 MapViewOfFileを使って自分自身のファイル ビューを作成しなければなりません。ファイル マッピング オブジェクトのハンドルを取得するには、 オブジェクトの名前を指定してOpenFileMapping関数を呼び出すのが最も簡単です。ファイル マッピング オブジェクトに名前がないときは、 プロセスは、 継承や複製によってオブジェクトのハンドルを取得しなければなりません。継承や複製について詳しくは、 プロセスとスレッドの概要およびハンドルとオブジェクトの概要を参照してください。

MapViewOfFileは、 ファイル ビューを指すポインタを返します。複数のプロセスがそれぞれ固有のポインタを使って同じデータを共有するには、 ファイルのすべてのビューを同じファイル マッピング オブジェクトから作成しなければなりません。この場合、 ファイル ビューが同等であるといいます。通常、 ファイル マッピング オブジェクトが同じファイルを参照していても、 異なるファイル マッピング オブジェクトから作成したファイル ビューは同等ではありません。

ファイル ビューはファイルではなくメモリのブロックであるため、 プログラムは、 ReadFile関数やWriteFile関数ではなく、 ReadProcessMemory関数とWriteProcessMemory関数を使ってファイル ビューを読み書きしなければなりません。

1つ以上のプロセスが共有データへの書き込みアクセスを持つ場合、 プロセスどうしは、 セマフォを使って共有データへのアクセスを同期しなければなりません。これによって、 ファイル ビューはどのプロセスでも同等になります。同期について詳しくは、 同期の概要を参照してください。

一部のアプリケーションでは、 複数のプロセスの同じアドレスにファイルをマップしなければならない場合があります。プロセスのアドレス空間の特定の位置にファイル ビューをおくには、 必要なアドレスを指定してMapViewOfFileEx関数を呼び出してください。指定されたアドレスに十分な領域がなければ、 この関数は失敗します。

CreateFileMappingはリモート ファイルにも有効ですが、 リモート ファイルの同等性を保つことはできません。たとえば、 2つのマシンがファイルを書き込み可能としてマップしており、 両方のマシンが同じページを変更した場合、 各マシンは、 自分が書き込んだ結果しか見ることができません。データがディスクに更新されるときも、 両方からの変更は統合されません。

メモリ ブロックの共有

ファイルに関連付けられていないメモリ ブロックを複数のプロセスが共有しなければならない場合、 いずれかのプロセスは、 既存のファイル ハンドルではなく (HANDLE) 0xFFFFFFFFを指定してCreateFileMapping関数を呼び出さなければなりません。対応するファイル マッピング オブジェクトは、 オペレーティング システムのページング ファイルのメモリをアクセスします。オペレーティング システムのページング ファイルを共有するプロセスは、 名前付きのファイルを共有するときと同様に、 MapViewOfFile関数かMapViewOfFileEx関数を使ってファイル ビューを作成しなければなりません。

ファイル ビューのクローズ

プロセスは、 共有メモリを使い終わったら、 UnmapViewOfFile関数を呼び出して、 自分のアドレス空間内のファイル ビューを破棄してください。この関数は、 共有メモリを指すポインタを無効化します。ビューがマップされてからファイル ビューのページのいずれかが変更されているときは、 この関数は、 変更されたページを物理ファイルにコピーします。

ファイル ビューから物理ファイルに特定のバイト数をコピーするには、 FlushViewOfFile関数を使ってください。FlushViewOfFileは、 ファイル ビューを破棄しません。

アプリケーション間でデータを共有するほかの方法については、 動的データ交換管理ライブラリの概要を参照してください。

ファイル マッピングの使用

このトピックのコード例は、 2つのプロセスが既存のファイルを名前付き共有メモリとしてアクセスする方法を示しています。

いずれか一方または両方のプロセスが共有メモリに書き込む場合、 プロセスどうしは、 セマフォを使ってメモリへのアクセスを同期しなければなりません。同期について詳しくは、 同期の概要を参照してください。

次に示すコードのCreateFileMapping関数は、 ファイル マッピング オブジェクトを作成します。プロセスは、 対応するファイル ビューを作成すると、 メモリへの読み書きアクセスができるようになります。

hMapFile = CreateFileMapping(hFile,/* current file handle */
(LPSECURITY_ATTRIBUTES) NULL,/* no security*/
PAGE_READWRITE,/* read-write access*/
0,/* max. object size is */
0,/* size of hFile*/
"MyFileMappingObject"); /* name of map. object */

if (hMapFile == NULL) {
ErrorHandler("Could not create file-mapping object.");
}

次に示すコードは、 CreateFileMappingが返したファイル マッピング オブジェクトのハンドルを使って、 ファイルのビューをプロセスのアドレス空間に作成します。

lpMapAddress = MapViewOfFile(hMapFile, /* handle to map. object */
FILE_MAP_ALL_ACCESS,/* read-write access*/
0,/* max. object size is*/
0,/* size of hFile*/
0);/* map entire file*/

if (lpMapAddress == NULL) {
ErrorHandler("Could not map view of file.");
}

MapViewOfFile関数は、 ファイル ビューを指すポインタを返します。プロセスは、 このポインタを使ってメモリにアクセスし、 必要な処理を行うことができます。

次の例では、 2番目のプロセスはOpenFileMapping関数を使って同じメモリを共有します。元のプロセスと同様に、 MapViewOfFile関数はファイル ビューを指すポインタを返します。

hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, /* r-w access*/
FALSE,/* do not inherit*/
"MyFileMappingObject"); /* name of mapping obj. */

if (hMapFile == NULL) {
ErrorHandler("Could not open file-mapping object.");
}

lpMapAddress = MapViewOfFile(hMapFile, /* hndl. to map. obj. */
FILE_MAP_ALL_ACCESS,/* read-write access*/
0,/* max. object size is */
0,/* size of hFile*/
0);/* map entire file*/

if (lpMapAddress == NULL) {
ErrorHandler("Could not map view of file.");
}

MapViewOfFileは、 異なるプロセスに対しては異なるアドレスを返します。プロセスのアドレス空間内でのファイル ビューの位置を指定するには、 MapViewOfFileではなくMapViewOfFileEx関数を使ってください。

次に示す例は、 UnmapViewOfFile関数を使って、 マップされているメモリを指すポインタを無効化します。この関数は、 プロセスのアドレス空間内のファイル ビューを破棄します。また、 ファイル ビューがマップされてからファイル ビューのページのいずれかが変更されている場合、 UnmapViewOfFileは、 変更されたページを物理ファイルにコピーします。

if (!UnmapViewOfFile(lpMapAddress)) {
ErrorHandler("Could not unmap view of file.");
}

FlushViewOfFile関数は、 指定されたバイト数をファイル ビューから物理ファイルにコピーしますが、 ファイル ビューを破棄しません。

if (!FlushViewOfFile(lpMapAddress, dwBytesToFlush)) {
ErrorHandler("Could not flush memory to disk.");
}

ファイル マッピング関数

ファイル マッピングに関する関数を次に示します。

CreateFileMapping

FlushViewOfFile

MapViewOfFile

MapViewOfFileEx

OpenFileMapping

UnmapViewOfFile

▲ページトップに戻る

【本を読んでもよくらからない】 … 個別指導でわかりやすくお教えします