运维开发网

C/C中的全缓冲,行缓冲和无缓冲

运维开发网 https://www.qedev.com 2022-05-06 16:09 出处:网络
这篇文章主要介绍了C/C++的全缓冲、行缓冲和无缓冲的相关知识,帮助大家更好的理解和学习c/c++,感兴趣的朋友可以了解下

这篇文章主要介绍了C/C++的全缓冲、行缓冲和无缓冲的相关知识,帮助大家更好的理解和学习c/c++,感兴趣的朋友可以了解下

1 .简介

在C/C++中,基于I/O流的操作最终会调用系统接口read()和write()来完成I/O操作。为了使程序高效运行,流对象通常提供缓冲区来减少对系统I/O接口的调用次数。

缓冲的方式有三种,分别是:
(1)全缓冲。或者输入和输出缓冲区已满,将执行实际的I/O操作。其他情况,如强制刷新和进程终止,也会执行实际的I/O操作。

对于读操作,当读入内容的字节数等于缓冲区大小或者文件已经到达末尾,或者强制刷新时,会执行实际的I/O操作,将外部文件的内容读入缓冲区;对于写操作,当缓冲区被填满或强制刷新时,将执行实际的I/O操作,并将缓冲区的内容写入外部存储文件。磁盘操作通常是完全缓冲的。

(2)行缓冲。或者输入输出缓冲区在遇到换行符时会执行实际的I/O操作。与其他满缓冲区相同。

(3)无缓冲。如果没有缓冲区,数据将被立即读入内存或输出到外部文件和设备。标准的错误输出stderr是无缓冲的,可以保证错误信息及时反馈给用户,以便用户消除错误。

头文件lt中定义了三种缓冲类型的宏;stdio.hgt。

缓冲类型 宏 全缓冲 _IOFBF 行缓冲 _IOLBF 无缓冲 _IONBF

Linux环境下,下面的代码可以很好的体现全缓冲和行缓冲的区别。

#include lt;stdio.hgt;#include lt;stdlib.hgt;int glob=6; int main(int argc, char** argv){ int var; pid_t pid; printf("a write to stdout\n"); if(pid=fork()lt;0) { printf("fork error"); } else { if(pid==0) { glob++; var++; } else { sleep(2); } } printf("pid=%d,glob=%d,var=%d\n",getpid(),glob,var); exit(0); }

编译成功后默认生成A.out,运行结果如下:

。/a . out
对stdout的写入
pid=4823,glob=7,var=4195873
pid=4824,glob=7,var=4195873

。/a.out gt。temp . txt
cat temp . txt
对stdout的写入
pid=4864,glob=7,var=4195873
对stdout的写入
pid=4865,glob=7,var = 4195873

可以看出,printf输出到标准输出(显示器)时是一个行缓冲区。当遇到换行符时,它会将缓冲区的内容输出到显示器,并清空空缓冲区。当使用redirect命令时,标准输出被重定向到磁盘文件。此时,标准输出变为完全缓冲。当遇到换行符时,它不会被输出,而是被复制到子进程中。父子流程结束后,每个流程都会有一个输出。

2.缓冲器的设置

(1)函数setbuf()或setbuffer()可用于打开或关闭缓冲区。参数buf指向缓冲区,表示缓冲区开启,通常是满缓冲区。将buf参数设置为NULL表示缓冲已关闭。注意setbuffer()是非C标准库函数,在Linux中很常见。

setbuf()的缓冲区长度至少为BUFSIZ(在stdio.h中定义),否则可能会发生缓冲区溢出。Setbuffer可以指定缓冲区大小。

//@header:stdio.h//@brief:设置指定的缓冲区或关闭缓冲//@param:stream:文件指针;buffer:缓冲区地址//@notice:使用默认缓冲大小BUFSIZ(在stdio.h中定义)void setbuf ( FILE * stream, char * buffer );//@notice:同setbuf,但可指定缓冲区大小void setbuffer(FILE *stream, char *buf, size_t size);

将缓冲区指定为NULL以关闭标准输出缓冲区。

setbuf(stdout,NULL)

指定的缓冲区。

static char newBuffer[BUFSIZ];//至少是BUFSIZ(定义在stdio.h),否则存在缓冲溢出可能setbuf(stdout,(char*)amp;newBuffer);//或者指定缓冲区大小static char newBuffer[512];setbuffer(stdout,(char*)amp;newBuffer,512);

(2)要改变缓冲模式,可以使用函数setvbuf()。

//@header:stdio.h//@brief:更改缓冲模式并设置缓冲区//@param:stream:文件指针;buf缓冲区地址;type:缓冲区模式;size:缓冲区大小//@ret:0成功,非0失败int setvbuf(FILE *stream, char *buf, int type, unsigned size);

例如,当流缓冲区设置为行缓冲区时,调用setvbuf()时,缓冲区地址设置为NULL,缓冲区大小设置为0。注意,前提是有缓冲。

setvbuf(stream,NULL,_IOLBF,0); //将缓冲改为行缓冲//上面的代码等价于setlinebuf(stream); //for Linux

如果对setvbuf的调用指定缓冲区大小大于0且buffer buf为NULL,则提交给setvbuf for malloc应用程序缓冲区。

//间接申请1024字节全缓冲区setvbuf(stream,NULL,_IOFBF,1024);

以上是C/C++中关于全缓冲、行缓冲和无缓冲的所有细节。更多关于C/C++缓冲的信息

0

精彩评论

暂无评论...
验证码 换一张
取 消