Unbuffered low-level IO and Buffered high-level IO
2007-05-23 14:17
381 查看
[align=center]Unbuffered low-level IO and Buffered high-level IO[/align]
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函数,从而提升性能。
4,例子
[1] 父进程发送消息给子进程,子进程读取消息后返回,父进程等待子进程结束
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
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 <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
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);
}
程序的运行结果为:
解释一下:
[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,所以我们要特别注意这方面的问题。
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 |
[1] 父进程发送消息给子进程,子进程读取消息后返回,父进程等待子进程结束
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
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 <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
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,所以我们要特别注意这方面的问题。
相关文章推荐
- low level descriptors and high level descriptors
- F4 Function for low value and high value
- High Performance Ruby Part 3: non-blocking IO and web application scalability
- ###《High-level event recognition in unconstrained videos》
- php非缓冲查询数据库三种mysqli,pdo,mysql方式(Bufferedand Unbuffered queries)
- Kafka High Level API vs. Low Level API
- low level and hight level structure in CNN
- OGRE基础教程四 Frame Listeners and Unbuffered Input
- 【一步一步的积累】Auto-context and Its Application to High-level Vision Tasks
- unix环境高级编程之unbuffered io
- Using the High-Level Input and Output Functions
- Adaptive Deconvolutional Networks for Mid and High Level Feature Learning(阅读)
- comparing c++ and c# -- a perspective from high level languages such as C#
- 第四章 Frame Listeners and Unbuffered Input
- What is Angular 2? High level overview, feature and fundamentals.
- 人群密度估计--CNN-based Cascaded Multi-task Learning of High-level Prior and Density Estimation for Crowd
- MemSQL Start[c]UP 3.0 - Round 2 and Codeforces Round #437 (Div. 1) D. Buy Low Sell High
- zabbix监控磁盘IO low-level-discory方式-iostat说明
- 每日论文Transient Attributes for High-Level Understanding and Editing of Outdoor Scenes
- High-level, multiplatform C++ network packet sniffing and crafting library