Windows system >> Windowsの知識 >  >> Windowsチュートリアル合成 >> 窓について >> Windowsでのプロセス間通信とデータ共有

Windowsでのプロセス間通信とデータ共有

  

Windows
ソケット、パイプ、メールスロットなどを使用して、プロセス間通信を実装する方法はたくさんあります。しかし最も基本的で最も直接的な用途はメモリ共有です。他の方法は結局ここで迂回するでしょう。

物理メモリが1つしかない場合は、このメモリを異なるプロセスでそれぞれの仮想アドレス空間にマッピングし、各プロセスで同じデータを読み取ることができます。データ交換の最も効率的な方法実装方法を説明しましょう。

共有メモリは、FileMappingを使用してWindowsに実装されています。 CreateFileMapping APIは、ファイルをメモリにマッピングするためのカーネルオブジェクトを作成します。ここでは、実際のファイルは必要ないので、ファイルを作成するためにCreateFileを呼び出す必要はありませんhFileパラメータは、INVALID_HANDLE_VALUEを使用して入力できます。ただし、ファイル長を埋める必要があります。 Windowsは最大64ビットのファイルをサポートしていますが、ここでは4Gを超えてはいけません、dwMaximumSizeHighは0でなければならず、長さはdwMaximumSizeLowで埋められます。次にMapViewOfFileを呼び出して、現在のプロセスの仮想アドレスにマップします。共有メモリを使い果たしたら、UnmapViewOfFileを呼び出してメモリアドレス空間を再利用します。

Windowsでは、CreateFileMapping APIとMapViewOfFile APIが分離されています。これは、4Gを超えるファイルのマッピングが可能であり、アドレス空間が最大でも4Gしかないため(実際のユーザーのプログラムでは2Gしか使用できない)、MapViewOfFileはファイルのオフセットを指定し、部分のみをマッピングできます。

CreateFileMappingの最後のパラメータにpszNameが名前を入力すると、他のプロセスがこの名前を使用してOpenFileMappingを呼び出してFileMappingオブジェクトを開き、それを新しいプロセスにマッピングできます。しかし、文字列に同意する方法はそれほどエレガントではないようです。

エレガントな方法は、DuplicateHandleを使用して新しいプロセス内のFileMappingオブジェクトをコピーし、メッセージを渡すなど、新しいプロセスにHandleに通知する方法を見つけることです。

メモリを共有する必要がある2つのプロセスが親子関係の場合は、メッセージを渡さずにFileMapping Handleに通知できます。親プロセスは、Handleを継承することでFileMappingのHandleを直接子プロセスに渡すことができます。もちろん、CreateFileMappingを作成するときに継承できるプロパティを設定する必要があります。

これについて:

SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; handle = CreateFileMapping(INVALID_HANDLE_VALUE、& sa、) PAGE_READWRITE、0、size、NULL);

したがって、CreateProcessでは、bInheritHandlesパラメータがTRUEの場合、継承可能なプロパティを持つすべてのカーネルオブジェクトが子プロセスにコピーされます。

注:カーネルオブジェクトの継承はCreateProcessで子プロセスを作成することですが、子プロセスのメインスレッドがアクティブになる前に、カーネルは現在のプロセス内のすべてのカーネルオブジェクトをスキャンし、継承可能なプロパティを持つオブジェクトをチェックアウトしてDuplicateHandleを使用します。子プロセスにコピーを作成します。これはカーネルオブジェクトなので、カーネル内にはコピーが1つだけあり、それらのコピーはすべて1つの参照カウントに1を加えたものになります親プロセスと子プロセスは、同じカーネルオブジェクトに対して同じハンドルを持つ必要があります。

カーネルオブジェクトをコピーするプロセスはCreateProcessによって内部的に行われますオブジェクトのHandle(子プロセスと同じ)をコマンドライン経由で子プロセスに安全に渡すことができます。あるいは、環境変数とともに渡すこともできます。

子プロセスがこのFileMappingオブジェクトを使い果たした後は、CloseHandleから参照カウントを引いたものが必要になります。

注:CreateProcessが呼び出されると、pszCommandLineは変更不可能な文字列を直接埋められません。例:

CreateProcess(" test.exe"、"テスト引数"、...);

"テスト引数"はコンパイラによってコンパイルされるため、これは誤りです。変更不可能なデータセグメントに入れます。正しい方法は次のとおりです。

char cmdline [] ="テスト引数"; CreateProcess(" test.exe"、cmdline、...);

このように、コマンドライン文字文字列はスタックに置かれ、読み書きすることができます。

CreateProcessの最後から2番目のパラメータは、STARTUPINFOW構造体に入力する必要がありますこの構造体は非常に複雑で、通常は入力するのに非常に手間がかかります。親プロセスの構造をコピーして適切に変更することができます。メソッドは次のとおりです。

STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi; GetStartupInfo(& si); CreateProcess(...、& si、& pi);

ここでは、GetStartupInfo(& si)が正しく実行されるように、STARTUPINFO構造体の最初の長さ情報を通常は入力する必要があります。

Copyright © Windowsの知識 All Rights Reserved