Inter-process-communication-named-pipes
プロセス間通信-名前付きパイプ
パイプは、関連するプロセス間の通信を目的としていました。 ある端末からクライアントプログラムを実行し、別の端末からサーバープログラムを実行するなど、無関係なプロセス通信にパイプを使用できますか? 答えはノーだ。 次に、無関係なプロセスの通信をどのように達成できるか、簡単な答えは名前付きパイプです。 これは関連するプロセスで機能しますが、関連するプロセスの通信に名前付きパイプを使用する意味はありません。
一方向通信に1本のパイプを使用し、双方向通信に2本のパイプを使用しました。 名前付きパイプにも同じ条件が適用されますか? 答えはノーです。名前付きパイプは双方向通信をサポートしているため、双方向通信(サーバーとクライアント、さらにクライアントとサーバー間の通信)に使用できる単一の名前付きパイプを使用できます。
名前付きパイプの別の名前は* FIFO(先入れ先出し)*です。 名前付きパイプを作成するシステムコール(mknod())を見てみましょう。これは一種の特別なファイルです。
このシステムコールは、通常のファイル、デバイスファイル、FIFOなどの特別なファイルまたはファイルシステムノードを作成します。 システムコールの引数は、パス名、モード、およびdevです。 モード名とデバイス情報のパス名。 パス名は相対パスです。ディレクトリが指定されていない場合、現在のディレクトリに作成されます。 指定されるモードは、次の表に示すように、ファイルのタイプやファイルモードなどのファイルタイプを指定するファイルモードです。 devフィールドは、メジャーおよびマイナーデバイス番号などのデバイス情報を指定するためのものです。
File Type | Description | File Type | Description |
---|---|---|---|
S_IFBLK | block special | S_IFREG | Regular file |
S_IFCHR | character special | S_IFDIR | Directory |
S_IFIFO | FIFO special | S_IFLNK | Symbolic Link |
File Mode | Description | File Mode | Description |
---|---|---|---|
S_IRWXU | Read, write, execute/search by owner | S_IWGRP | Write permission, group |
S_IRUSR | Read permission, owner | S_IXGRP | Execute/search permission, group |
S_IWUSR | Write permission, owner | S_IRWXO | Read, write, execute/search by others |
S_IXUSR | Execute/search permission, owner | S_IROTH | Read permission, others |
S_IRWXG | Read, write, execute/search by group | S_IWOTH | Write permission, others |
S_IRGRP | Read permission, group | S_IXOTH | Execute/search permission, others |
ファイルモードは、0XYZなどの8進表記でも表すことができます。Xは所有者を表し、Yはグループを表し、Zはその他を表します。 X、Y、またはZの値の範囲は0〜7です。 読み取り、書き込み、実行の値はそれぞれ4、2、1です。 読み取り、書き込み、実行の組み合わせで必要な場合は、それに応じて値を追加します。
たとえば、0640と言えば、所有者には読み取りと書き込み(4 + 2 = 6)、グループには読み取り(4)、その他には許可なし(0)を意味します。
この呼び出しは、成功すると0を返し、失敗すると-1を返します。 失敗の原因を知るには、errno変数またはperror()関数で確認してください。
このライブラリ関数は、名前付きパイプに使用されるFIFO特殊ファイルを作成します。 この関数の引数は、ファイル名とモードです。 ファイル名は、絶対パスでも相対パスでもかまいません。 フルパス名(または絶対パス)が指定されていない場合、実行プロセスの現在のフォルダーにファイルが作成されます。 ファイルモード情報は、mknod()システムコールで説明されているとおりです。
この呼び出しは、成功すると0を返し、失敗すると-1を返します。 失敗の原因を知るには、errno変数またはperror()関数で確認してください。
ある端末でサーバーを実行し、別の端末でクライアントを実行するプログラムを考えてみましょう。 このプログラムは、一方向の通信のみを実行します。 クライアントはユーザー入力を受け入れ、サーバーにメッセージを送信し、サーバーは出力にメッセージを印刷します。 ユーザーが文字列「end」を入力するまで、プロセスは継続されます。
例でこれを理解しましょう-
- ステップ1 *-2つのプロセスを作成します。1つはfifoserverで、もう1つはfifoclientです。
- ステップ2 *-サーバープロセスは以下を実行します-
- 「MYFIFO」という名前の名前付きパイプを(システムコールmknod()を使用して)作成します(作成されていない場合)。
- 読み取り専用の名前付きパイプを開きます。
- ここでは、所有者の読み取りと書き込みの権限を持つFIFOを作成しました。 グループの読み取り、その他のアクセス許可はありません。
- クライアントからのメッセージを無限に待機します。
- クライアントから受信したメッセージが「終了」ではない場合、メッセージを出力します。 メッセージが「終了」の場合、FIFOを閉じてプロセスを終了します。
- ステップ3 *-クライアントプロセスは以下を実行します-
- 書き込み専用の名前付きパイプを開きます。
- ユーザーからの文字列を受け入れます。
- ユーザーが「終了」または「終了」以外を入力したかどうかを確認します。 いずれにせよ、サーバーにメッセージを送信します。 ただし、文字列が「終了」の場合、これによりFIFOが閉じられ、プロセスも終了します。
- ユーザーが文字列「end」を入力するまで無限に繰り返します。
次に、FIFOサーバーファイルを見てみましょう。
コンパイルおよび実行手順
では、FIFOクライアントのサンプルコードを見てみましょう。
到着した出力を見てみましょう。
コンパイルおよび実行手順
名前付きパイプを使用した双方向通信
パイプ間の通信は単方向であることを意図しています。 パイプは一般に一方向通信に制限されており、双方向通信には少なくとも2本のパイプが必要です。 パイプは、相互に関連するプロセス専用です。 パイプは無関係なプロセスの通信に使用できません。たとえば、ある端末から1つのプロセスを実行し、別の端末から別のプロセスを実行する場合、パイプでは不可能です。 2つのプロセス間で通信する簡単な方法はありますか? 答えはイエスです。 名前付きパイプは、2つ以上の無関係なプロセス間の通信を目的としており、双方向通信も可能です。
すでに、名前付きパイプ間の一方向の通信、つまりクライアントからサーバーへのメッセージを見てきました。 ここで、双方向通信、つまり、クライアントがサーバーにメッセージを送信し、サーバーがメッセージを受信し、同じ名前付きパイプを使用して別のメッセージをクライアントに送信することを見てみましょう。
以下は例です-
- ステップ1 *-2つのプロセスを作成します。1つはfifoserver_twoway、もう1つはfifoclient_twowayです。
- ステップ2 *-サーバープロセスは以下を実行します-
- /tmpディレクトリに「fifo_twoway」という名前の名前付きパイプを(ライブラリ関数mkfifo()を使用して)作成します(作成されていない場合)。 * 読み取りおよび書き込み目的で名前付きパイプを開きます。 * ここでは、所有者の読み取りと書き込みの権限を持つFIFOを作成しました。 グループの読み取り、その他のアクセス許可はありません。 * クライアントからのメッセージを無限に待ちます。 * クライアントから受信したメッセージが「終了」ではない場合、メッセージを出力して文字列を反転します。 反転した文字列はクライアントに送り返されます。 メッセージが「終了」の場合、FIFOを閉じてプロセスを終了します。
- ステップ3 *-クライアントプロセスは以下を実行します-
- 読み取りおよび書き込み目的で名前付きパイプを開きます。
- ユーザーからの文字列を受け入れます。
- ユーザーが「終了」または「終了」以外を入力したかどうかを確認します。 いずれにせよ、サーバーにメッセージを送信します。 ただし、文字列が「終了」の場合、これによりFIFOが閉じられ、プロセスも終了します。
- メッセージが「終了」ではないとして送信された場合、クライアントからのメッセージ(反転した文字列)を待機し、反転した文字列を出力します。
- ユーザーが文字列「end」を入力するまで無限に繰り返します。
では、FIFOサーバーのサンプルコードを見てみましょう。
コンパイルおよび実行手順
では、FIFOクライアントのサンプルコードを見てみましょう。