5

これは、名前付きパイプを開き、文字列を書き込み、パイプを閉じる単純なコードです。以下で説明するように、パイプは別の関数で作成されます。

char * ipcnm = "./jobqueue";

std::cout << "opening job queue" << std::endl;

//ensure the jobqueue is opened
if ((jobq = open(ipcnm, O_WRONLY)) < 0) {
  perror("open");
  exit(-1);
}

std::cout << "queue opened" << std::endl;

// record the number of bytes written to the queue
size_t written = write(jobq, ptr, size*nmemb);

// close fifo
if (close(jobq) < 0) {
  perror("close");
  exit(-1);
}

// need to report to other agents the size of the job that was written
jobSizes.push_back(written);

しかし、open() の呼び出しがハングします。呼び出し時に fifo "jobqueue" を使用するプロセスが他にないことと、キューが作成された後のキューのファイル権限が prwxrwxr-x に設定されていることを確認しました (mkfifo(ipcnm, 0777)パイプの作成に使用しているだけです。

o最初は、そのグループにこのパイプのアクセス許可がないことが問題だと思ったwので、chmod を使用して手動で変更しましたが、「キューが開いています」が出力されないため、ハングします。perror("open"); のエラー メッセージも表示されません。

私は何が欠けていますか?

4

2 に答える 2

17

書き込み用に FIFO を開くと、リーダーが存在するまでライターはブロックされます。

あなたはおそらくリーダーを見逃しています。

パイプに書き込み、それを閉じて、後でリーダーを使用することはできません。このようなストレージ セマンティクスは、通常のファイルを使用して実現されます。

パイプはプロセス間通信メカニズムです。FIFO を開くことによって作成されたパイプは、pipePOSIX C ライブラリ関数によって返されるオブジェクトに似ていpipeますが、2 つの記述子があるため、既に I/O 用に準備されたオブジェクトを返す点が異なります。 . 一方、FIFO のエンドポイントは一度に 1 つずつ個別に開かれます。

ファイルシステム内の FIFO オブジェクトは、複数のプロセスが同じパイプにアタッチできる接点にすぎません。

最初は、パイプ オブジェクトは存在しません。最初のプロセスがopenファイルシステム内の FIFO オブジェクトに対して を実行すると、パイプが作成されます。open同じプロセスまたは別のプロセスからの追加の要求は、カーネルに保持されている同じパイプ オブジェクトにアタッチされます。パイプが読み取り用に少なくとも 1 回、書き込み用に少なくとも 1 回開かれるまで、I/O は発生しません。実際のパイプ I/O はカーネルを経由します。ファイルシステムには保存されません。すべてのプロセスがパイプを閉じると、オブジェクトは消えます。

FIFO は、プロセスが読み取り用にオブジェクトをオープンする前に I/O を開始できるように設計できます。つまり、書き込み要求を続行することを許可し、パイプがいっぱいになった場合にのみブロックすることができます。その設計には問題があります。たとえば、パイプがいっぱいにならないように書き込みが小さい場合はどうなるでしょうか。ライターはデータを書き込み、その実行を続行します。リーダーがデータを読み取る前に単に終了した場合、データは永久に消えてしまいます! ブロック動作により、データをキャッチするリーダーが存在することが保証されます。ライターのブロックが解除されると、リーダーがパイプを開いていることを確認できるため、データが失われることなくパイプの端を安全に閉じることができます。リーダーが使用できない場合でも書き込みをブロックしない設計では、開いているプロセスがない場合でもパイプ オブジェクトをカーネル内に保持する必要があります。ライターがパイプを開き、そこにデータを入れてから立ち去り、後でリーダーがデータを取得できるようにします。そうでなければ、デザインはライターにブロッキングを提供する必要がありますclose(SO_LINGERソケットでの -arranged 動作と同様に) 以前に書き込まれたデータが削除されるのを待ちます。

于 2014-06-07T17:18:39.383 に答える