1

背景
私はFIFOで遊んでいて、FIFOに書き込もうとするたびに、誰かがfdの反対側を読み取るまでブロックします。

int fd;
char buffer[100] = {0};
char * myfifo = "/tmp/myfifo";    

mkfifo(myfifo, 0666);
printf("What would you like to send?\n");
fgets(buffer, 100, stdin);

if((fd = open(myfifo, O_WRONLY)) < 0)
    printf("Couldn't open the FIFO for writing!\n");
else {
    write(fd, buffer, strlen(buffer));
    close(fd);

/tmp/myfifoこのコードは機能しますが、サイドを読み取ってデータを取得するまでブロックされます。そのようにコードを変更すると:

if((fd = open(myfifo, O_WRONLY | O_NONBLOCK)) < 0)

No such device or address次に、 「読み取り」側で誰かがブロックされて座っていない限り、オープンはエラーで失敗します。

分析マニュアルページによるとfifo()
The kernel maintains exactly one pipe object for each FIFO special file that is opened by at least one process. The FIFO must be opened on both ends (reading and writing) before data can be passed. Normally, opening the FIFO blocks until the other end is opened also.

したがって、これは予想される操作です。

質問

私の実験と私が読んでいることに基づいて... FIFOはキューに入れられず、バッファに入れられないメカニズムであり、データを待機しているプロセスがある場合にのみ機能すると想定する必要があります。

ブロックされていないバッファ付きマナー、基本的にはバッファ付きFIFOで機能する別の通信メカニズムはありますか、それとも独自のメッセージストレージ/通知システムを作成する必要がありますか?

編集

私は「遊んでいる」と言っていますが、これは実際にはかなり説明的です。さまざまなIPCメカニズム(FIFO、ソケット、およびパイプ)の詳細を学習しようとしています。私はselect()、selectを呼び出すスリーププロセスをウェイクアップするために何を使用できるかを学び、理解することに取り組んでいます。それが新しいプラットフォームへの移植について分析しているコミュニケーションドライバーの一部である理由。
これは無関係なので、元の投稿から除外しました。私は、(現時点で)FIFO、それらの使用方法、それらの制限、およびその他のIPCメカニズムを理解できるようにしようとしています。したがって、データを格納し、ブロックせずに書き込むことができるFIFOの「より良い」バージョンに関する私の当初の仮定/質問。

4

1 に答える 1

2

FIFO はバッファリングされるだけでなく、基本的に FIFO のすべてです。FIFO は、カーネル内のバッファーにすぎません。

説明:カーネルには、プロセスが読み取り用に FIFO を開いている場合を除き、バッファへのデータの書き込みを拒否するというポリシーがあります。この動作はパイプと TCP 接続に似ていますが、パイプまたは TCP 接続のリーダーがない場合、カーネルは実際に書き込みプロセスにシグナルを送り、終了します (ハンドラーをインストールしない限り)。この動作により、期待どおりにコマンドを並べることができます。

hexdump file.dat | head

hexdumpプログラムは、head数行を読み取ると強制終了されます。これは 99% の確率で必要なことでhexdumpあり、これを実現するために特別なコードは必要ありません。

解決策:解決しようとしている問題について、もう少し背景を説明していただけると助かります。

  1. クライアントが読み取ることができるメッセージをサーバーがキューに入れるクライアント/サーバー システムが必要な場合は、Unix ドメイン ソケットを使用してこれを実現できます。Unix ドメイン ソケットは FIFO に似ていますが、さまざまな点でより柔軟です。(ほとんどのデータベース サーバーは、他のタイプの IPC よりも Unix ドメイン ソケットを優先します。)

  2. アプリケーションが個別にメッセージをエンキューおよびデキューできる永続キューを格納できるようにする場合は、通常のファイルを使用する必要があります。

残念ながら、「FIFO をいじる」ということはあまり続きません。IPC の演習が必要な場合は、Unix ドメイン ソケットまたは TCP (または両方を同時に使用しますが、それほど難しくありません) を使用するチャット サーバーを作成してみてください。telnetまたはnc(netcat) をクライアントとして使用できます。(「OpenBSD」バージョンの netcat があることを確認してください。)

于 2012-09-28T17:21:24.630 に答える