第119章 匿名パイプ その1


プロセスとプロセスをつなぐのに、「パイプ」というものがあります。

パイプには「匿名パイプ」と「名前付きパイプ」があります。

今回から、匿名パイプについてやります。

パイプを作るプロセスをサーバー、他のプロセスをクライアントと呼びます。 匿名パイプはサーバーからクライアント、またはクライアントからサーバーへの 通信のみができます。また、他のコンピュータとは通信できません。



匿名パイプを作るには、CreatePipe関数を使います。

BOOL CreatePipe(
  PHANDLE phReadPipe,                      
  PHANDLE phWritePipe,                      
  LPSECURITY_ATTRIBUTES lpPipeAttributes, 
  DWORD nSize                             
);
phReadPipeiには、読み取り側ハンドルへのポインタを指定します。

phWritePipeには、書き込み側ハンドルへのポインタを指定します。

lpPipeAttributesには、SECURITY_ATTRIBUTES構造体へのポインタを指定します。

SECURITY_ATTRIBUTES構造体は、次のように定義されています。

typedef struct _SECURITY_ATTRIBUTES { 
  DWORD  nLength; 
  LPVOID lpSecurityDescriptor; 
  BOOL   bInheritHandle; 
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES; 
nLengthは、この構造体のバイト数です。

lpSecurityDescriptorは、セキュリティデスクリプタへのポインタです。

bInheritHandleは、新しいプロセスが作られたときハンドルを継承するかどうかを指定します。

さて、CreatePipe関数のnSize引数に戻ります。

これには、パイプのサイズを指定します。0を指定するとデフォルトのサイズが割り当てられます。

パイプを作ってから、いきなり子プロセスを作ってはいけません。

匿名パイプは、一方通行なので読み取りハンドルか、書き込みハンドルのどちらか一方を 子供に継承できないようにしておく必要があります。

これには、DuplicateHandle関数を使います。

本来DuplicateHandle関数は、ハンドルの複製を作成するものですが、こんな使い方もできるわけです。

BOOL DuplicateHandle(
  HANDLE hSourceProcessHandle,  // 複製元プロセスのハンドル
  HANDLE hSourceHandle,         // 複製対象のハンドル
  HANDLE hTargetProcessHandle,  // 複製先プロセスのハンドル
  LPHANDLE lpTargetHandle,      // 複製先ハンドル
  DWORD dwDesiredAccess,        // 複製ハンドルで必要なアクセス権
  BOOL bInheritHandle,          // ハンドル継承フラグ
  DWORD dwOptions               // オプションの動作
);
子プロセスを作る前に、書き込みハンドルを継承できないようにするには、 複製もとプロセスと、複製先プロセスを自分のプロセスにしておきます。

自分のプロセスのハンドルは、GetCurrentProcess関数で取得することができます。

また、複製先ハンドルをNULLにしておきます。アクセス権は0、継承フラグはFALSEに しておきます。もちろん対象ハンドルは書き込みハンドルです。

オプション動作は、DUPLICATE_SAME_ACCESSとしておきます。

これで、読み取りハンドルは子プロセスに継承できなくなります。

さて、子プロセスを作る方法はすでに第113章でやっているので復習してみてください。

STARTUPINFO si;
...
DuplicateHandle(
    GetCurrentProcess(),//ソースプロセス
    hWrite,//オリジナルハンドル
    GetCurrentProcess(),//ソースプロセスと同じ
    NULL,//複製ハンドルのポインタ NULLなので新規には作らない
    0,//アクセス権
    FALSE,//継承しない
    DUPLICATE_SAME_ACCESS);
...
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = hRead;
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
...
CreateProcess(image, command line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
と、こんな感じになります。

子プロセスでは、継承されたハンドルを使って、親からの通信を読み取ります。

具体的なプログラムは、次回からやっていきます。


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

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