私は、コンソールからユーザー入力を取り込み、別のスレッドで出力するプログラムに取り組んでいます。ユーザーが何かを入力している途中で、printf が表示されてカーソル位置に表示されるような状況は避けたいと思います。
コンソール ウィンドウから c で非ブロック io を実行する方法はありますか? 理想的には、ユーザーが入力したものが画面に表示されないように、キープレスなどをキャプチャします。私は Ubuntu で開発を行っていますが、ncurses などを使用する必要がなければ最高です。
私は、コンソールからユーザー入力を取り込み、別のスレッドで出力するプログラムに取り組んでいます。ユーザーが何かを入力している途中で、printf が表示されてカーソル位置に表示されるような状況は避けたいと思います。
コンソール ウィンドウから c で非ブロック io を実行する方法はありますか? 理想的には、ユーザーが入力したものが画面に表示されないように、キープレスなどをキャプチャします。私は Ubuntu で開発を行っていますが、ncurses などを使用する必要がなければ最高です。
を使用termios
すると、端末のエコーを無効にできます。
#include <termios.h>
struct termios oflags, nflags;
tcgetattr(fileno(stdin), &oflags);
nflags = oflags;
nflags.c_lflag &= ~ECHO;
nflags.c_lflag |= ECHONL;
if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) {
/* handle error */
}
次に、終了する前に (を使用atexit
)、端末を復元する必要があります。
if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) {
/* handle error */
}
HP フォーラムから直接取得した、C からのエコーをオフにする方法の例を次に示します(個人的にはテストしていません)。
これは、エコーをオフにする簡単な例です。
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <termios.h> #define STDIN_FDES 0 struct termios save; int main(int argc, char *argv[]) { int cc = 0; char s_tmp[80],*p = NULL; struct termios work; cc = tcgetattr(STDIN_FDES,&save); work = save; work.c_lflag &= ~(ECHO); cc = tcsetattr(STDIN_FDES,TCSANOW,&work); (void) printf("\nEnter value: "); (void) fflush(stdout); p = fgets(s_tmp,sizeof(s_tmp),stdin); if (p != NULL) (void) printf("Out -> %s\n",p); cc = tcsetattr(STDIN_FDES,TCSANOW,&save); return(cc); }
注: SIGINT、SIGTERM などをキャッチし、元の termios を使用して端末をリセットするためのシグナル ハンドラーを用意することは非常に重要です。これは、最後の tcsetattr() が優先され、これが単にプロセスではなく端末デバイスに適用されるためです。エコーをオフにしてプロセスを終了すると、シェルでもオフになります。
それ以外の場合、Bash が適切なアプローチである場合は、どうやらstty -echo
.
あなたの質問を正しく理解していれば、エコーをオフにするか、非ブロッキング I/O を使用することは答えではありません。むしろ、バックグラウンド スレッドがユーザー入力スレッドを中断しないようにする必要がありますよね?
そのためには、ラインバッファ入力の代わりに生のキープレスにアクセスする必要があります。あなたが ncurses や同様のライブラリにアレルギーを持っている理由がわかりません。それが彼らの目的です!それがあなたのやり方なら、termiosまたはioctl呼び出しでそれを行うことができると思います....
しかし、マルチスレッド TTY 出力の問題を解決するには、次のようにします。
1) コンソールにアクセスできるユーザーを制御するミューテックスを作成する
バックグラウンド スレッドで、メッセージを出力するには:
ミューテックスを取得します。メッセージを書きます。ミューテックスを解放します。寝返って!
ユーザー入力スレッドで:
新しい入力が検出されたときにミューテックスを取得します。ユーザーが Enter キーを押すまで排他アクセスを保持し、ミューテックスを解放して、バックグラウンド スレッドに対話の機会を与えます。
それは役に立ちますか?