ブロックせずにUnixコンソールアプリで単一のキーストロークをキャプチャするにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/184108

  •  06-07-2019
  •  | 
  •  

質問

Cで書かれた非常に単純なTCPサーバーがあります。これは無期限に実行され、接続を待機しています。 Windowsでは、 select を使用してソケットのアクティビティを確認します。ない場合は、キーボードで「q」を押して終了できるようにする次のコードがあります。

if( kbhit() ) {
   char c = getch();
   if( c == 'q' ) break;
}

kbhit が存在せず、 getch の動作が異なるため、Unixでは動作しません。 サンプルコードが見つかりました tcsetattr を使用して端末設定を変更し、文字ごとの入力を許可します。 init関数を呼び出した後、/ dev / stdinを( O_NONBLOCK で)開いて文字を読み取りますが、文字まで read(f、& c、1)はブロックしますヒットします。

別のスレッドを生成し、 it を無期限に待機させ、ユーザーが「q」を押した場合に最初のスレッドにシグナルを送ることができると思いますが、それは少し手間がかかりそうです。簡単な方法はありますか?

役に立ちましたか?

解決

選択ハンドルのリストにstdinを追加し、データがある場合は、readを呼び出してそこから1文字を読み取ります。

他のヒント

むしろ、" f"を追加しますあなたの

から
read( f, &c, 1 )

コールを選択します。 fの読み取り準備ができた時点で、文字が押され、read()はブロックされません。

Unixでは、システムコンソール上でもXターミナルウィンドウでも、キーボードI / Oは仮想ターミナルを通過します。デバイス/ dev / ttyは、最近ではプロセスの制御端末にアクセスする通常の方法です。 open / close / read / write以外のデバイス操作はすべて、その特定のデバイスのioctl(2)システムコールによって処理されます。あなたがしたいことの一般的な考え方は

です

制御端末を開きます(stdinである場合とそうでない場合があります)

入力の全行を待たずに戻るように、その端末の動作モードを変更します(これは通常のデフォルトです)

プログラムの残りの部分を続けて、その端末(標準入力である可能性があります)からの読み取りは、エラーまたは終了条件にならずに、部分的な行またはゼロ文字を返す場合があることを理解しています。


2番目のステップの実行方法に関する詳細な回答は、 CプログラミングのFAQ 。また、これはOSの質問であり、言語の質問ではないことも指摘しています。それらは9つの可能性を提供しますが、この質問に関連する3つの主要なものは次のとおりです

  1. curses(3)ライブラリを使用する
  2. 古いBSDスタイルのシステムでは、sgttybを使用してCBREAKまたはRAWを設定します
  3. Posixまたは古いSystem Vスタイルのシステムでは、TCGETAW / TCSETAWを使用してc_cc [VMIN]を1に、c_cc [VTIME]を0に設定します。

C FAQのいくつかの参照に従うと、 kbhitコードフラグメントのこのページにつながる可能性があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top