IO を間違って実行しています。POSIX マニュアルと他のすべての関連ドキュメントでは、FILE * で行われた IO を決して混在させないように明示的に述べています。 s およびファイル記述子。あなたはこのルールをあからさまに破っています。 FILE * のため、このルールが適用されます バッファリングを使用する これは、 fgets への呼び出しの後に read には何も残らない fgets のため取得する FILE * に保持されているすべての保留中のデータをバッファーに既に読み込んでいます 構造。
したがって、ISO C IO メソッドがブロックされるかどうかを確認する方法がないため、ファイル記述子のみを使用する必要があります。
 STDIN_FILENO がわかっているので は数字の 0 です。
fcntl (0, F_SETFL, O_NONBLOCK);
 これにより、すべての read が変わります s on file descriptor 0 to non-blocking mode. 別のファイル記述子を使用して 0 をそのままにしておく場合は、dup を使用します。 複製します。
 このようにして、poll から離れることができます ngetc を完全に実装する として
ssize_t 
ngetc (char *c)
{
  return read (0, c, 1);
}
できればマクロ
#define ngetc(c) (read (0, (c), 1))
したがって、探しているものを簡単に実装できます。
編集: 端末が入力をバッファリングすることをまだ心配している場合は、いつでも端末の設定を変更できます。プログラムから xterm で入力の行バッファリングを無効にする方法を参照してください。これを行う方法の詳細については、
 編集: fgetc が使えなかった理由 read の代わりに fgets を使用するのと同じ理由です 動作しません。 FILE * のいずれかの場合 IO 関数が実行され、関連するファイル記述子からすべてのデータが読み取られます。しかし、それが起こると、 poll 常に空のファイル記述子を待機しているため、決して返されません。同じことが read でも発生します。 .したがって、ドキュメントのアドバイスに従い、決してしないことをお勧めします。 ミックスストリーム (fgets を使用した IO 、 fgetc など) と ファイル記述子 (read を使用した IO 、 write など)