2016-10-02 5 views
0

私はGNUのlibcのマニュアルからthisコードテストしていた?でも、端末かかわら私はまだ入力がさえ非標準モードで読み出して出力させるために「Enterキーを押す必要があるのはなぜ

#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <termios.h> 

/* Use this variable to remember original terminal attributes. */ 

struct termios saved_attributes; 

void 
reset_input_mode (void) 
{ 
    tcsetattr (STDIN_FILENO, TCSANOW, &saved_attributes); 
} 

void 
set_input_mode (void) 
{ 
    struct termios tattr; 
    char *name; 

    /* Make sure stdin is a terminal. */ 
    if (!isatty (STDIN_FILENO)) 
    { 
     fprintf (stderr, "Not a terminal.\n"); 
     exit (EXIT_FAILURE); 
    } 

    /* Save the terminal attributes so we can restore them later. */ 
    tcgetattr (STDIN_FILENO, &saved_attributes); 
    atexit (reset_input_mode); 

    /* Set the funny terminal modes. */ 
    tcgetattr (STDIN_FILENO, &tattr); 
    tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */ 
    tattr.c_cc[VMIN] = 1; 
    tattr.c_cc[VTIME] = 0; 
    tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr); 
} 

int 
main (void) 
{ 
    char c; 

    set_input_mode(); 

    while (1) 
    { 
     read (STDIN_FILENO, &c, 1); 
     if (c == '\004')   /* C-d */ 
     break; 
     else 
     putchar (c); 
    } 

    return EXIT_SUCCESS; 
} 

を非標準モードに設定された、私はまだ入力が受けられるようにするために、Enterキーを押す必要があり

をしかし、私は変更する場合:私は思ったようputchar(c)write(STDOUT_FILENO, &c, sizeof(char))に、それが正常に動作

答えて

2

をあなたがされています。ユーザーのバッファリングによって駄目になった!putchar(3)はlibc I/O APIの一部ですが、write(2)はシステムコールです。システムコールはありませんが、今のところそれを考慮しましょう。

libcには、バッファなし、ブロックバッファ、行バッファの3種類のバッファリングがあります。ストリームがバッファリングされていない場合、データは書き込まれるとすぐに基礎となるファイル(または端末)に送られます。ブロックされたブロックの場合、データはいっぱいになるまでメモリブロックに保存され、一度にすべて書き込まれます。ただし、行バッファリングの場合、改行文字が見つかると、ファイル(または端末)にデータが送信されます。

ストリームが端末に接続されている場合、通常は標準出力の場合と同様に、ラインバッファリングされます。これはあなたの場合です。Enterを押すと、改行文字\nは(行)バッファを標準出力に書き出します。ただし、write(2)を呼び出すと、libc バッファリングのユーザーがバイパスされ、対応するファイル記述子(STDOUT_FILENO)にデータが書き込まれます。

これまで述べたように、write(2)はシステムコールです。実際にはwriteを呼び出すと、システムコールにライブラリラッパーを呼び出しています。システムコールは、システムコールが従う厳密なプロトコル(例えば、引数などが必要な場所)を処理します。

ところで、私がここで言ったことはすべて、putchar(3)write(2)setbuf(3)のmanページにあります。カッコ内の数字は、マニュアルのセクションを参照しています。2はシステムコール、3はライブラリ関数用です(man manはセクションとそのトピックのリストを提供する必要があります)。

希望します。

+1

すぐに 'putchar()'を返す方法として 'setvbuf(stdout、0、_IONBF、0)'を挙げることができます。それとも、私はそれをやっただけで十分です。 (putchar( '[')、putchar(c)、などのように、出力に表示される文字が通常は端末によってエコーされるのではないことを確信させるために何かをやろうと思っているでしょう。 putchar( ')';の代わりに '' putchar( '') –

関連する問題