2009-07-26 22 views
3

Linuxで動作するように設計されたCで書かれた小さなアプリがあります。アプリの一部は、キーボードからのユーザー入力を受け入れ、非標準的な端末モードを使用して、各キーストロークに応答することができます。Linux端末で非正規の端末I/Oアプリケーションに問題がある

入力を受け付けるコードのセクションは、ループで繰り返し呼ばれる単純な関数である:

char get_input() 
{ 
    char c = 0; 
    int res = read(input_terminal, &c, 1); 
    if (res == 0) return 0; 
    if (res == -1) { /* snip error handling */ } 
    return c; 
} 

これは、端末から単一の文字を読み取ります。特定の時間枠内に入力がない場合(termios構造体のc_cc [VTIME]値で指定)、read()は0を返し、get_input()が再び呼び出されます。

このアプリケーションは、端末ウィンドウでこのアプリケーションを実行してから、アプリケーションを終了せずに終了すると、アプリケーションは終了せずにCPU集中型の無限ループに起動しますread()は待機せずに0を返し続けます。

ターミナルウィンドウから実行して端末ウィンドウを閉じた場合、アプリを正常に終了させるにはどうすればよいですか?問題は、read()が-1を返さないということです。なぜなら、read()が0を返す通常のケースと区別できないエラー条件です。私が見る唯一の解決策は、タイマーを入れて、 readは、c_cc [V_TIME]で指定された時間よりも速く0を返します。しかし、その解決策は最高だと思われます。私は、このような状況に対処するより良い方法があると考えていました。

アイデアや提案はありますか?

答えて

1

プログラムを終了する前に信号を捕まえてリセットしていますか?私はSIGHUPがあなたが集中する必要があるものだと思います。 read()から戻ってクリーンアップして終了するときにスイッチがオンになっている場合は、おそらくシグナルハンドラのスイッチを設定します。

0

ReadはEOFで0を返します。私。正常に何も読み取られません。 この場合、関数は0を返します。

あなたがすべきことは、readから返された値を1と比較して例外を処理することです。 I.あなたは1つを求めましたが、1つを取得しましたか?

-1が返された場合は、おそらくerrno == EINTRを処理することになります。

 
char get_input() 
{ 
     char c = 0; 
     int res = read(input_terminal, &c, 1); 
     switch(res) { 
     case 1: 
       return c; 
     case 0: 
       /* EOF */ 
     case -1: 
       /* error */ 
     } 
} 
1

タイムアウトは、端末の設定ではなく選択で処理する必要があります。端末がタイムアウトなしで設定されている場合は、EOF以外の場合は0を返しません。

Selectはタイムアウトを与え、readは閉じると0を返します。

rc = select(...); 
if(rc > 0) { 
     char c = 0; 
     int res = read(input_terminal, &c, 1); 
     if (res == 0) {/* EOF detected, close your app ?*/} 
     if (res == -1) { /* snip error handling */ } 
     return c; 
} else if (rc == 0) { 
    /* timeout */ 
    return 0; 
} else { 
    /* handle select error */ 
} 
関連する問題