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であるため,我々は特にこの方面の問題に注意しなければならない.