linux文件缓冲区
2011年01月27日
一:缓冲区机制
根据应用程序对文件的访问方式,即是否存在缓冲区,对文件的访问可以分为带缓冲区的操作和非缓冲区的文件操作:
缓冲区文件操作:高级文件系统,将在用户空间中自动为正在使用的文件开辟内存缓冲区。
非缓冲区文件系统:低级文件系统,如果需要,只能由用户在自己的程序中为每个文件设定缓冲区。
如果采用非缓冲的文件访问方式,每次对该文件进行一次读写操作时,都需要使用读写文件系统掉用来处理该操作,因此,如果用户需要访问某个磁盘文件,则每访问一次都要执行一次系统调用,执行一次系统调用将涉及到CPU状态的切换,即从用户空间切换到内核空间,实现上下文的切换,这将损耗一定的CPU时间,频繁的磁盘访问对程序的执行效率造成很大的影响。
ANSI标准C库函数建立在底层系统调用之上,即C函数库文件访问函数的实现中使用了低级文件I/O系统调用,ANSI标准C库中的文件处理函数为了减少使用系统调用的次数,提高效率,根据应用的不同,采用缓冲区机制,这样,在对磁盘文件进行读操作时,可以一次从文件中读出大量的数据到缓冲区中,以后对这部风的访问就不需要在使用系统调用了,即只需要少量的CPU状态切换。在对文件进行写操作时,可以先将内容存在缓冲区,待文件写满后,或者确实需要更新时在调用系统调用将文件一次写入到磁盘中。
二:缓冲区类型
标准 I/O 提供了 3 种类型的缓冲区。
1,全缓冲区:这种缓冲区要求填满整个缓冲区后才进行 I/O 系统调用操作。对于磁盘
文件通常使用全缓冲区访问。第一次执行 I/O 操作时,ANSI 标准的文件管理函数通过调用
malloc 函数获得需使用的缓冲区。默认大小为 8192。
//come from /usr/include/stdio.h
/* Default buffer size. */
#ifndef BUFSIZ
# define BUFSIZ _IO_BUFSIZ //BUFSIZ 全局宏定义
#endif
//come from /usr/include/libio.h
#define _IO_BUFSIZ _G_BUFSIZ
//come from /usr/include/_g_config.h
#define _G_BUFSIZ 8192 //真实大小
刷新(flush)操作即标准 I/O 缓冲区的写操作。它可以由系统自动完成(当填满一个缓
冲区时)或者调用函数 fflush()或 flush()实现。
2,行缓冲区:在这种情况下,当在输入和输出中遇到换行符时,标准 I/O 库执行 I/O
系统调用操作。当流涉及一个终端时(例如标准输入和标准输出),使用行缓冲区。因为标准I/O 库收集的每行的缓冲区长度是固定的,只要填满了缓冲区,即使还没有遇到换行符,也将执行 I/O 系统调用操作。默认行缓冲区大小为 128 字节。
3,无缓冲区:标准 I/O 库不对字符进行缓存。如果用标准 I/O 函数写若干字符到不带
缓冲区的流中,则相当于用 write 系统调用函数将这些字符写至相关联的打开文件。标准出错流 stderr 通常是不带缓冲区的,这使得出错信息能够尽快地显示出来。
对于标准输入输出设备,ANSI C 要求具有以下缓冲区特征:
l 标准输入和标准输出设备:当且仅当不涉及交互作用设备时,标准输入流和标准输
出流才是全缓冲区的。
l 标准错误输出设备:标准出错决不会是全缓冲区的。
对于任何一个给定的流,可以调用 setbuf()和 setvbuf()函数更改其缓冲区类型。
1, 名称:: setbuf 功能: 更改文件流的缓冲区位置 头文件: #inlcude 函数原形: void setbuf (FILE * restrict stream, char * restrict buf) 参数: stream 要操作的流对象
buf 指定的缓冲区 返回值: 若成功则返回0,若出错则为非0 此函数第一个参数为要操作的流对象,第二个参数 buf 必须指向一个长度为 BUFSIZ 的
缓冲区。如果将 buf 设置为 NULL,则关闭缓冲区。
如果执行成功,将返回 0,否则返回非 0 值。
2, 名称:: setvbuf 功能: 更改文件流的缓冲区位置 头文件: #inlcude 函数原形: int setvbuf (FILE * restrict stream, char *restrict buf, int modes,size_t n) 参数: stream 要操作的流对象
buf 指定的缓冲区
mode 缓冲区类型
n buf的大小 返回值: 若成功则返回0,若出错则为非0 /* Make STREAM use buffering mode MODE. If BUF is not NULL, use N bytes of it for buffering;else allocate an internal buffer N bytes long. */
此函数第一个参数为要操作的流对象;第二个参数 buf 必须指向一个长度为 BUFSIZ 的
缓冲区;第三个参数为缓冲区类型,分别定义如下:
//come from /usr/include/stdio.h
/* The possibilities for the third argument to 'setvbuf'. */
#define _IOFBF 0 /* Fully buffered. */ //全缓冲
#define _IOLBF 1 /* Line buffered. */ //行缓冲
#define _IONBF 2 /* No buffering. */ //无缓冲
第四个参数
为该 buf 的大小。如果指定一个不带缓冲区的流,则忽略 buf 和 size 参数。
如果指定全缓冲区或行缓冲区,则 buf 和 size 可选择地指定一个缓冲区及其长度。如果指定该流是带缓冲区的,而 buf 是 NULL,则标准 I/O 库将自动为该流分配适当长度的缓冲适当长度指的是由文件属性数据结构(struct stat)的成员 st_blksize 所指定的值,如果系统不能为该流决定此值(例如若此流涉及一个设备或一个管道),则分配长度为 BUFSIZ 的缓冲区。
此函数如果执行成功,将返回 0,否则返回非 0 值。
以下是一个修改 buf 大小写文件的实例程序。其源代码如下:
int main( int argc , char ** argv ) { int i; FILE * fp; char msg1[]="hello,wolrd\n"; char msg2[] = "hello\nworld"; char buf[128]; /*打开(或者创建)一个文件,然后使用 setbuf 设置为 nobuf 情况,并检查关闭前流的情况*/ if(( fp = fopen("no_buf1.txt","w")) == NULL) { perror("file open failure!"); return(-1); } setbuf(fp,NULL); //设置为无 buf fwrite( msg1 , 7 , 1 , fp ); //写内容 printf("test setbuf(no buf)!check no_buf1.txt\n"); //查看 buf 情况 printf("press enter to continue!\n"); getchar(); fclose(fp); //关闭流,因此将回写 buf(如果有 buf 的话) /打开(或者创建)一个文件,然后使用 setvbuf 设置为 nobuf 情况,并检查关闭前流的情况*/ if(( fp = fopen("no_buf2.txt","w")) == NULL) { perror("file open failure!"); return(-1); } setvbuf( fp , NULL, _IONBF , 0 ); //设置为无 buf fwrite( msg1 , 7, 1 , fp ); //写内容 printf("test setvbuf(no buf)!check no_buf2.txt\nbecause line buf, only before enter data write\n"); printf("press enter to continue!\n"); getchar(); fclose(fp); //关闭流,因此将回写 buf(如果有 buf 的话) /*打开(或者创建)一个文件,然后使用 setvbuf 设置为行 buf 情况,并检查关闭前流的情况*/ if(( fp = fopen("l_buf.txt","w")) == NULL) { perror("file open failure!"); return(-1); } setvbuf( fp , buf , _IOLBF , sizeof(buf) );//设置为行 buf fwrite( msg2 , sizeof(msg2) , 1 , fp ); //写内容 printf("test setvbuf(line buf)!check l_buf.txt, because line buf , only data before enter send to file\n"); printf("press enter to continue!\n"); getchar(); fclose(fp); //关闭流,因此将回写 buf //打开(或者创建)一个文件,然后使用 setvbuf 设置为全 buf 情况,并检查关闭前流的情况 if(( fp = fopen("f_buf.txt","w")) == NULL) { perror("file open failure!"); return(-1); } setvbuf( fp , buf , _IOFBF , sizeof(buf) ); for(i = 0 ; i { fputs( msg1 , fp ); } printf("test setbuf(full buf)!check f_buf.txt\n"); printf("press enter to continue!\n"); getchar(); fclose(fp); //关闭流,因此将回写 buf } 其编译过程及运行结果如下:
[root@localhost linux_app]# ./setbuf_example
test setbuf(no buf)!check no_buf1.txt//在按回车键前需要先查看当前目录下的 no_buf1.txt 内容
press enter to continue!
test setvbuf(no buf)!check no_buf2.txt//在按回车键前需要先查看当前目录下的 no_buf2.txt 内容
because line buf, only before enter data write
press enter to continue!
test setvbuf(line buf)!check l_buf.txt, because line buf ,only data before enter send to file
press enter to continue! //在按回车键前需要先查看当前目录下的 l_buf.txt 内容
test setbuf(full buf)!check f_buf.txt
press enter to continue! //在按回车键前需要先查看当前目录下的 f_buf.txt 内容
以下内容是在过程中查看各文件内容信息:
[root@localhost linux_app]# cat no_buf1.txt
hello,w //写入的 7 个字符全部写入到文件中
[root@localhost linux_app]# cat no_buf2.txt
hello,w //写入的 7 个字符全部写入到文件中
[root@localhost linux_app]# cat l_buf.txt
hello //只有回车前的字符写入
[root@localhost linux_app]# cat f_buf.txt //没有任何内容写入
运行过程完成后:
[root@localhost linux_app]# cat no_buf1.txt
hello,w //与原来内容一样
[root@localhost linux_app]# cat no_buf2.txt
hello,w //与原来内容一样
[root@localhost linux_app]# cat l_buf.txt
hello
world //因为调用了 fclose()函数,刷新了缓冲区,将 world 写入
[root@localhost linux_app]# cat f_buf.txt
hello
world //因为调用了 fclose()函数,刷新了缓冲区,将 hello\nworld 都写入
发表评论
-
C和C++之间库的互相调用
2012-01-20 12:20 643C和C++之间库的互相调用 2011年01月19日 1. ... -
字母大小写转换可以不用循环吗
2012-01-20 12:20 716字母大小写转换可以不用循环吗 2011年03月22日 2 ... -
VC6下将ANSI程序转化为UNICODE基本步骤
2012-01-20 12:20 1219VC6下将ANSI程序转化为UNI ... -
Linux0.11内核--汇编和C语言混合编程之参数传递
2012-01-20 12:20 767Linux0.11内核--汇编和C语言混合编程之参数传递 2 ... -
3月编程语言排行榜:C#超Python和PHP
2012-01-19 17:01 8043月编程语言排行榜:C#超Python和PHP 2011年0 ... -
python os模块
2012-01-19 17:01 1013python os模块 2011年05月22日 os.l ... -
2010年IT薪酬报告:java,apex,python,windows技术最赚钱
2012-01-19 17:01 7722010年IT薪酬报告:java,apex ... -
python 实现多台UNIX服务器自动巡检
2012-01-19 17:01 1828python 实现多台UNIX服务器自动巡检 2012年01 ... -
初学Python有感!!!
2012-01-19 17:01 566初学Python有感!!! 2011年01月25日 ... -
VC++6.0实现超链接
2012-01-17 06:46 1203VC++6.0实现超链接 2011年 ... -
经典的串口调试助手源代码(一)
2012-01-17 06:46 838经典的串口调试助手源代码(一) 2011年05月26日 ... -
经典的串口调试助手源代码(一)
2012-01-17 06:46 1123经典的串口调试助手源代码(一) 2011年04月26日 ... -
转 Windows API 函数在VFP中的运用
2012-01-17 06:46 1177转 Windows API 函数在VFP中的运用 2010年 ... -
VB-2.1
2012-01-17 06:46 678VB-2.1 2011年09月26日 Option E ... -
越南攻略
2012-01-16 05:36 565越南攻略 2010年07月02日 ... -
去越南相亲吧~~~~~
2012-01-16 05:36 587去越南相亲吧~~~~~ 2011年05月04日 越南,一 ... -
谷歌找客户的方法
2012-01-16 05:35 566谷歌找客户的方法 2011年12月16日 Wind怎么利 ...
相关推荐
概括介绍Linux的缓冲区管理,对linux的缓冲区管理进行说明,以pdf格式发布ppt格式的文件
Linux文件系统数据缓冲区的分析研究.pdf
linux 缓冲区溢出 漏洞攻击 获取root权限 shell
【2】服务器两个线程,一个线程负责读文件进入缓冲区,另一个线程负责发送文件数据。 【3】客户端两个线程,一个线程负责接收文件进入缓冲区,另一个线程负责写文件数据。 【4】服务器端,命令行./Server_NBuffer 要...
Linux系统编程学习-第2天标准IO缓冲区文件操作
4、理解缓冲区在文件系统中的作用。 三、实验内容 1、理解open 函数和close函数的调用过程; 2、理解read 函数和write函数的调用过程; 3、利用上述函数实现文件的复制过程,并利用缓冲区来减少系统调用次数。
Linux下的进程间的文件传输,通过服务器和客户端间加入缓冲区 完成文件读取和写入
帧缓冲-GOL Conway's Game of Life 使用 Linux 帧缓冲区实现。 这是一个用 C 编写的有趣的小实验,准系统写入 Linux 帧缓冲设备。 The Game of Life 令人着迷,Linux 帧缓冲区是一个很好的画布。 如果在启动程序时...
get进程负责不断地把原始文件内容送入缓冲区s中,copy进程负责从缓冲区s中取出上述内容复制到缓冲区t中,而put进程负责把上述内容从缓冲区t中取出复制到目标文件中,用p、v操作实现这三个进程之间的同步。...
【2】服务器两个线程,一个线程负责读文件进入缓冲区,另一个线程负责发送文件数据。 【3】客户端两个线程,一个线程负责接收文件进入缓冲区,另一个线程负责写文件数据。 【4】服务器端,命令行./Server_NBuffer 要...
缓冲区溢出简单实例,里面有三个实例,都是简单的c代码,其中第一个实在linux下运行的,库文件有点问题
在Linux环境下实现一个多线程对...其中get负责从文件F_in中把数据块读入并输出缓冲区S,copy负责从S中提取数据块并复制到缓冲区T中,put负责从缓冲区T中取出信息存入到本地文件F_out中。实现get、copy、put的操作过程。
1\write不用关闭即写入到文件,没有缓冲区,比较低级的操作方式。Fwrite有缓冲区,所以fwrite更高效。不用总是写硬盘。所以以后要选用fwrite方式。 2\fwrite移植性好。 3\若在同一进程中,用两种方式打开不同文件(或...
2.8.1 减少缓冲区和页缓存大小 25 2.8.2 换出System V共享内存页 26 2.8.3 换出和淘汰页 27 2.9 交换缓存 27 2.10 页换入 28 第3章 进程 29 3.1 Linux进程 29 3.2 标识符 31 3.3 调度 32 3.4 文件 34 3.5 虚拟内存 ...
Linux内核分析与应用课件
IO操作,即输入/输出操作,是指...缓冲IO: 数据首先被读取到一个内存缓冲区,然后再从缓冲区移动到最终的目的地。 同步与异步IO: 同步IO要求操作完成后程序才继续运行,而异步IO允许程序在操作还在进行时继续其他任务。
u-dma-buf是Linux设备驱动程序,用于在内核空间中分配连续的内存块作为DMA缓冲区,并使它们在用户空间中可用。 当用户应用程序使用UIO(用户空间I / O)在用户空间中实现设备驱动程序时,打算将这些存储块用作DMA...
第一章 走进linux 1.1 GNU与Linux的成长 1.2 Linux的开发模式和运作机制 ...2.4 Linux内存管理中Slab缓冲区 2.5 Linux中的VFS 2.6 Linux的连网 2.7 网络设备支持 2.8 模块支持 2.9 硬件接口 2.10 块设备 2.11 USB 设备
QT QSerialPort 封装,阻塞方式发送数据后等待读取缓冲区数据结果,使用QT信号量阻塞,线程中初始化串口和读取数据。
u-dma-buf(用户空间可映射 DMA 缓冲区)\n概述\nu-dma-buf介绍\nu-dma-buf 是一个 Linux 设备驱动程序,它在内核空间中分配连续的内存块作为 DMA 缓冲区,并使它们在用户空间中可用。当用户应用程序使用 UIO(用户...