Unbuffered low-level IO and Buffered high-level IO



Unbuffered low-level IO and Buffered high-level IO
1,概要
Unixが提供する関数、例えばread、writeなどは、Unbuffered IO関数に属します.
Standard IOが提供する関数、例えばfread、fwriteはBuffered IO関数に属する.Standard IOの下位層はread,writeを呼び出して実現される.
2,Unbuffered
Unbufferedは、readを呼び出すたびにwriteがカーネルのシステム呼び出しを引き起こし、ファイルを実際に読み書きすることを意味します.
3,Buffered
Bufferはreadを最小限に抑えるためにwrite関数を呼び出し、パフォーマンスを向上させる.
Stream
Buffering type
Stderr
Always unbufferer
Streams referring to a
Terminal (interactive) device
Line Bufferer
All other streams
Full Buffer
4、例
[1]親プロセスは子プロセスにメッセージを送信し、子プロセスはメッセージを読み込んだ後に戻り、親プロセスは子プロセスの終了を待つ
#include
#include
#include
#include
 
int main() {
pid_t pid ;
int fd[2] ;
int rtn ;
 
pipe( fd ) ;
pid = fork() ;
if ( pid == 0 ) { //child
              close ( fd[1] ) ;
              char info[56]= { 0 } ;
              dup2( fd[0] , stdIN_FILENO ) ;
             //read( fd[0] , info , 56 ) ;
              read( stdIN_FILENO , info , 56 ) ;
ß
親プロセスから送信された情報を読み込む
              printf("child from parent: %s/n", info);
              close ( fd[0] ) ;
             
              return 0 ;
} else { //parent
              char * pstr = "parent send to child : ";
             
close( fd[0] ) ;
              dup2( fd[1] , stdOUT_FILENO ) ;
              printf("%s",pstr ); 
ß
なければ
fflush
呼び出すと、
child
次のようになります.
read
ブロック
              fflush( stdout ) ;   
ß
だから
fully buffered
/*パイプ内のプロセスの出力は、次のプロセスの入力として使用されます*/
             //write( fd[1] , pstr , strlen("parent: send to child/n") ) ;
             //write( stdOUT_FILENO , pstr , strlen("parent: send to child/n") ) ;
             //
以上のいずれかを使用すると、ブロック現象はありません.
unbuffered

 
              waitpid( pid , &rtn , 0) ;
ß
待ち受ける
child
の最後の部分
              close ( fd[1] ) ;
}
 
return 0 ;
}
 
[2]
#include
#include
#include
#include
 
int
     glob = 6 ;      
char
    buf[] = "a write to stdout/n";
 
int main(void) {
    pid_t     pid;
    int       var = 88 ;
    //write
はい
unbuffered
    write(stdOUT_FILENO, buf, sizeof(buf)-1) ;
    printf("before fork/n");   
ß
line buffered
を選択し、
interactive terminal
つながるなら
                            
ß
さもないと
fully buffered
 
    if ((pid = fork()) < 0) {
        printf("fork error");
        return (-1) ;
    } else if (pid == 0) { //child
        glob++;
        var++;
    } else { //parent
        sleep(2);
    }
 
    printf("pid = %d, glob = %d, var = %d/n", getpid(), glob, var);
    return (0);
}
プログラムの実行結果は次のとおりです.
$ ./a.out
a write to stdout
before fork
pid = 430, glob = 7, var = 89
pid = 429, glob = 6, var = 88
$ ./a.out > temp.out
$ cat temp.out
a write to stdout
before fork
pid = 432, glob = 7, var = 89
before fork
pid = 431, glob = 6, var = 88

説明します.
[1]writeはunbufferedなのでfork実行時にstdoutに出力されている.
[2]直接実行するとstdoutとinteractive terminalが接続されるのでline bufferedです.Printfが実行されるとstdoutに出力されます.文字列は改行で終わるからです.
[3]
リダイレクト実行を出力する場合、
stdout
ファイルにリダイレクト
temp.out
.だから
fully buffered
.
Printf
実行後、
stdout
に表示されます.後で実行しました
fork
、出力バッファもコピーされました
child
に表示されます.にある
parent
,
child
で、再実行
printf
の場合、実際には出力バッファにコンテンツを追加します.当
parent
または
child
終了時、出力バッファの内容は
flush
.
 
これらの問題はsubtleであるため,我々は特にこの方面の問題に注意しなければならない.