第107章 オーバーラップ・ファイルI/O その1


今回から、ファイルのオーバーラップについてやります。

ファイルの読み書きに時間がかかる時、これが終了するまで他の作業が できないのでは、困ります。このような場合、オーバーラップを利用するとになります。


これには、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と言うファイルを用意しておきます。

プログラムを実行すると、このファイルに「テスト書き込みです」と書き込まれます。

次回から、もう少し実際的な状態を作ってみます。


[Index][総合Index] [Previous Chapter] [Next Chapter]

Update Dec/06/2004 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。