次のように、関数fgetsを使用して、stdinからループを読み取るプログラムを作成しています。
while(fgets(buffer2, BUFFERSIZE , stdin) != NULL){
//Some code
}
コードを非ブロッキングにしたい、つまり、ユーザーからの入力がないときにプログラムが「fgets」行を保持したくない。
どうすればいいですか?
次のように、関数fgetsを使用して、stdinからループを読み取るプログラムを作成しています。
while(fgets(buffer2, BUFFERSIZE , stdin) != NULL){
//Some code
}
コードを非ブロッキングにしたい、つまり、ユーザーからの入力がないときにプログラムが「fgets」行を保持したくない。
どうすればいいですか?
fgets()
はブロッキング関数であり、データが利用可能になるまで待機することを意図しています。
非同期 I/O を実行する場合は、、、または を使用select()
できpoll()
ますepoll()
。利用可能なデータがある場合は、ファイル記述子から読み取りを実行します。
これらの関数は、以下によって取得された FILE* ハンドルのファイル記述子を使用します。
int fd = fileno(f);
Unix または Linux を使用している場合、1 つの解決策として、ファイルが使用するファイル記述子をノンブロッキングとしてマークすることができます。例:
#include <fcntl.h>
FILE *handle = popen("tail -f /als/als_test.txt", "r");
int fd = fileno(handle);
flags = fcntl(fd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags);
fgets
現在は非ブロックである必要があり、null を返し、エラー コードを設定します。
適切な POSIX 環境があれば、select()
orを使用して、 ...を呼び出す前に の記述子のpoll()
入力をチェックできます。stdin
fgets()
read()
以下の Jan のコメント (ありがとう!) は、このアプローチを使用できない理由を説明していますfgets()
... 要約すると、FILE
オブジェクトには追加のバッファリング層があり、データは既に待機している可能性がありますがselect()
、ファイル記述子には何も見つかりません.. . プログラムがタイムリーに応答できなくなり、さらに送信する前に他のシステムが既に送信されたデータへの応答を待機している場合、ハングする可能性がありstdin
ます。
基本的に2つのオプションがあります。
これは少しやり過ぎのように聞こえるかもしれませんが、これが私の頭に浮かぶものです。
2 つの異なるスレッドを使用します。1 つはこのループを使用し、ブロッキングを待機しています (これは非ブロッキングで実行できるとは思いません)。そして、何かが読み取られたら、それをパイプに押し込みます。
その間、他のスレッドは必要なことは何でも実行し、パイプ内のデータを時々チェックします (明らかに、これを非同期にしたい、または少なくとも私はこの方法で取得します。そうであれば、これは別のスレッドを意味します)
ただし、2 つのスレッドを十分に同期させる必要があります。マルチスレッドと IO 操作について OS を確認する必要があります。
Linux では、 ctrl-dを押すことで入力の終了を指定できます。もちろん、別のスレッドを使用してこれを行うこともできます。