ファイルの読み書きに時間がかかる時、これが終了するまで他の作業が できないのでは、困ります。このような場合、オーバーラップを利用するとになります。
これには、win32のAPI関数を利用します。
CreateFile, ReadFile, WriteFile関数については、すでにSDK編で解説があります。
オーバーラップI/Oを行うには、CreateFile関数の第3引数をFILE_SHARE_READ | FILE_SHARE_WRITEにします。
第6引数をFILE_FLAG_OVERLAPPEDにします。
これで、ファイルをオープンします。
関数が失敗すると、INVALID_HANDLE_VALUEが返されます。
他のスレッドや、プロセスが使用中の場合、でもFILE_SHARE_***で読み書きしている場合はエラーになりません。
さて、次にReadFile関数で読み出します。
この時、第5引数にOVERLAPPED構造体へのポインタを指定します。
OVERLAPPED構造体は次のように定義されています。
typedef struct _OVERLAPPED { ULONG_PTR Internal; ULONG_PTR InternalHigh; DWORD Offset; DWORD OffsetHigh; HANDLE hEvent; } OVERLAPPED;Internalや、InternalHighは内部的に予約済みです。
Offsetには、ReadFileやWriteFile関数のオフセットを指定します。
OffsetHighにはオフセットの上位WORD値を指定します。
hEventには、イベントハンドルを指定します。
ReadFile関数は読み取りが完了する前に制御を返すことがあります。
これにより、ReadFileに時間がかかる場合も、他の仕事をすることができます。
読み取り前に制御が返された時、この関数はFALSEを返します。
すぐに、GetLastError関数を呼び出すと、ERROR_IO_PENDINGが返されます。
WriteFile関数も同様に扱います。
さて、ペンディング中はGetOverlappedResult関数で待ちます。
BOOL GetOverlappedResult( HANDLE hFile, // ファイル、パイプ、通信デバイスのハンドル LPOVERLAPPED lpOverlapped, // オーバーラップ構造体 LPDWORD lpNumberOfBytesTransferred, // 転送されたバイト数 BOOL bWait // 待機オプション );bWaitにTRUEを指定すると、オーバーラップ操作が完了するまで待機します。
では、サンプルを見てみましょう。
/* overlap01.c */ #define MYFILE "c:\\test.txt" #include <stdio.h> #include <windows.h> int main() { HANDLE hFile, hEvent; OVERLAPPED ovl; BOOL bRet, bLError; char szBuf[64]; DWORD dwWritten; strcpy(szBuf, "テスト書き込みです"); hEvent = CreateEvent(NULL, FALSE, FALSE, "olp"); hFile = CreateFile(MYFILE, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("ファイルのオープンに失敗しました\n"); return -1; } memset(&ovl, 0, sizeof(OVERLAPPED)); ovl.hEvent = hEvent; bRet = WriteFile(hFile, szBuf, (DWORD)strlen(szBuf), &dwWritten, &ovl); if (!bRet) { bLError = GetLastError(); if (bLError == ERROR_IO_PENDING) { GetOverlappedResult(hFile, &ovl, &dwWritten, TRUE); } else { printf("エラーです"); CloseHandle(hFile); CloseHandle(hEvent); return -2; } } CloseHandle(hFile); CloseHandle(hEvent); return 0; }Cドライブのルートにtest.txtと言うファイルを用意しておきます。
プログラムを実行すると、このファイルに「テスト書き込みです」と書き込まれます。
次回から、もう少し実際的な状態を作ってみます。
Update Dec/06/2004 By Y.Kumei