さて、今回は実際に匿名パイプを作ってみます。
具体的作り方は前章を参照してください。
// 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;
}
パイプと、子プロセスを作成する関数です。DuplicateHandle関数の意味がわかりにくいので、前章でもう一度復習しておいて ください。
さて、このプログラムのみではうまく動作しません。これとは、別に"pipe01child.exe" という名前のプログラムが必要です。
親プロセスから書き込みをした内容がパイプを通じてpipe01child.exeに送信されます。
次回は、pipe01child.exeを作ります。
Update Feb/09/2006 By Y.Kumei