《Linux系统调用:setvbuf,setbuf,setbuffer,setlinebuf,fflush》

╄→гoц情女王★ 提交于 2019-12-16 04:10:59

一、介绍

// stdio 库函数
当操作磁盘文件时,缓冲大块数据以减少系统调用,C语言库函数I/O函数fprintf,fscanf(),fgets(),fputs(),fputc(),fgetc()等都是这么做的,stdio库函数可以使编程者免于自行处理对数据的缓冲。
运行在用户空间!下一篇说到运行在内核空间

二、接口定义

// 下列函数都是设置stdio流的缓冲模式

#include <stdio.h>

// 一般使用这个函数,可以设置参数替代下面的3个函数
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
参数: 
	stream : fopen 打开的流句柄
	buf,size: 如果不为空,那么其指向buf区域size大小的内存块作为流的缓冲区
	           所以应该是动态或者静态分配的一块空间
						 如果为空,stdio库会为stream自动分配一个缓冲区,就好像我们程序中
						 并没有执行这个系统调用,为什么会有行缓冲区
	mode:
		#define _IOFBF 0                /* Fully buffered.  */
		#define _IOLBF 1                /* Line buffered.  */
		#define _IONBF 2                /* No buffering.  */
	
	
		_IONBF // 不对I/O进行缓冲, 
		       忽略buf和size参数,可以指定NULL,0.stderr就是这类能立刻输出错误
		
		_IOLBF // 行缓冲I/O, 
		       终端设备的流默认属于这一类,程序输出如printf输出到stdout 默认是行缓冲
		
		_IOFBF // 全缓冲I/O, 
		       就是buf,size结合,读或者写必须达到指定的大小时候才进行输入输出

//相当于是 setvbuf(FILE *stream,buf,(buf!=NULL)? _IOFBF:_IONBF,BUFSIZ)
// BUFSIZ是多大?
/*
#define _G_BUFSIZ 8192  //8K
#define _IO_BUFSIZ _G_BUFSIZ
#ifndef BUFSIZ
# define BUFSIZ _IO_BUFSIZ
#endif
*/
void setbuf(FILE *stream, char *buf);

//相当于是 setvbuf(FILE *stream,buf,(buf!=NULL)? _IOFBF:_IONBF,size)
//就是可以指定size多大,而不是 BUFSIZ 大小
void setbuffer(FILE *stream, char *buf, size_t size);

// 设置行缓冲,相当于是 setvbuf(FILE *stream,NULL,_IOLBF,BUFSIZ)
void setlinebuf(FILE *stream);


// 无论当前采用何种缓冲区模式,任何时候都可以使用fflush库函数强制
// 将stdio输出流中的数据刷新到内核缓冲区中
int fflush(FILE *stream);
参数:
	stream: fopen打开的流句柄,若为空,将刷新所有的stdio缓冲区
					glibc中的C库函数实现中,若stdin和stdout指向同一终端,
					那么无论何时从stdin中读取输入时,都隐含调用了一次fflush()

返回值:
	成功返回0,错误返回EOF(-1)并设置errno				

三、实例

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>

char buf[512];
int main(int argc, char *argv[])
{
	int ret;
	

	// 不设置stdout 缓存模式时候,默认是
	// 行缓存,行缓存就是一行buf满了或者
	// 遇到换行符才输出,
	// 下面这个没有换行符,不会立刻输出
	printf("this is main func ");

	sleep(2); // sleep是为了更方便的看到上面现象
	printf("\n");// 这个时候才输出

#if 1
	// 设置没有缓冲模式
	ret = setvbuf(stdout,NULL,_IONBF,0);
	if(ret !=0)
		printf("setvbuf error \n");
	else
		printf("this is main func "); // 立刻输出但是不会换行

//#else
	sleep(2); 
	// 指定缓冲buf,并设置size
	memset(buf,0,sizeof(buf));
	ret = setvbuf(stdout,buf,_IOFBF,512);
	if(ret !=0)
		printf("setvbuf error \n");	
	else
	{
		printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); //首先9个字符A,不会输出,没满10个
		sleep(2);
		printf("B");
	}
#endif
	// test fflush
	#if 0
	sleep(2);
	fflush(stdout); // 调用会显示上面的AB
	#endif

	sleep(5); // 到这里为止都没有打印上面的AB
	return 0; // 直到main结束,隐含调用了fflush
}

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!