第120章 匿名パイプ その2


さて、今回は実際に匿名パイプを作ってみます。 具体的作り方は前章を参照してください。



// pipe01.c

#include <stdio.h>
#include <windows.h>

int WritePipe();
int MyCreateChildAndPipe();

HANDLE hWrite, hProcess;
int end;

int main()
{
    char ans[8];

    //子プロセスとパイプの作成
    MyCreateChildAndPipe();

    while (1) {
        printf("***** Menu *******\n");
        printf("1.パイプに書き込む\n");
        printf("0.終了\n");
        printf("******************\n");
        printf("--->");

        gets(ans);
        switch (ans[0]) {
            case '1':
                WritePipe();
                break;
            case '0':
                end = 1;
                WritePipe();
                break;
            default:
                printf("入力ミスです\n");
                break;
        }
        if (end == 1)
            break;
    }
    return 0;
}
プログラム開始とともに、MyCreateChildAndPipe関数で子プロセスと 匿名パイプを作ります。

次にメニューを表示してユーザーに指示を促します。

ここでは、書き込みをするのか、終了するのかを選択します。

書き込みをする場合はWritePipe関数を呼んで書き込みをします。

さて、終了時にはendグローバル変数を1にして、WritePipe関数を呼びます。

これは、終了時にちょっとした細工をするためです。

int WritePipe()
{
    char szBuf[256];
    DWORD dwResult, dwError;

    if (end != 1) {
        printf("書き込みをしてください--->");
        gets(szBuf);
    } else {
        strcpy(szBuf, "end");
    }
    if (!WriteFile(hWrite, szBuf, sizeof(szBuf), &dwResult, NULL)) {
        dwError = GetLastError();
        if (dwError == ERROR_BROKEN_PIPE || dwError == ERROR_NO_DATA) {
            printf("パイプがありません\n");
        } else {
            printf("何らかのエラーです\n");
        }
        CloseHandle(hWrite);
        hWrite = NULL;
        CloseHandle(hProcess);
        hProcess = NULL;
        return -1;
    }
    return 0;
}
パイプに書き込みをする関数です。

グローバル変数のendが1の時は、パイプに"end"と書き込みます。
これが、終了の合図となります。

endが1でないときは、ユーザーに書き込みを促します。
WriteFile関数でパイプに書き込みを行います。

int MyCreateChildAndPipe()
{
    HANDLE hRead;
    SECURITY_ATTRIBUTES sa;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    if (!CreatePipe(&hRead, &hWrite, &sa, 0)) {
        printf("パイプの作成に失敗しました\n");
        return -1;
    }
    if (!DuplicateHandle(GetCurrentProcess(), //ソースプロセス
            hWrite, //duplicateするハンドル(オリジナルハンドル)
            GetCurrentProcess(), //ターゲットプロセス(行先)
            NULL, //複製ハンドルへのポインタ(コピーハンドル)
            0, //アクセス権
            FALSE, //子供がハンドルを継承するかどうか
            DUPLICATE_SAME_ACCESS)) { //オプション
                printf("DuplicateHandle Error\n");
                CloseHandle(hWrite);
                CloseHandle(hRead);
                hWrite = NULL;
                return -2;
    }

    memset(&si, 0, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdInput = hRead;
    si.hStdOutput = GetStdHandle( STD_OUTPUT_HANDLE );
    si.hStdError = GetStdHandle( STD_ERROR_HANDLE );

    if (!CreateProcess(NULL, "pipe01child.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
        printf("CreateProcess Error\n");
        CloseHandle(hWrite);
        hWrite = NULL;
        return -3;
    } 

    hProcess = pi.hProcess;
    CloseHandle(pi.hThread);
    CloseHandle(hRead);

    return 0;
}
パイプと、子プロセスを作成する関数です。
この関数は、main関数から1度のみ呼ばれます。
CreatePipe関数で、パイプを作ります。

DuplicateHandle関数の意味がわかりにくいので、前章でもう一度復習しておいて ください。

さて、このプログラムのみではうまく動作しません。これとは、別に"pipe01child.exe" という名前のプログラムが必要です。

親プロセスから書き込みをした内容がパイプを通じてpipe01child.exeに送信されます。

次回は、pipe01child.exeを作ります。


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

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