ARM技术论坛
登录
直播中
emitter
6年用户
1884经验值
擅长:可编程逻辑 存储技术
私信
关注
[经验]
文件IO之缓冲
文件IO
缓冲
文件IO和标准I/O(缓冲IO)对比分析
1 文件I/O
文件I/O:文件I/O称之为不带缓存的IO(unbuffered I/O)。不带缓存指的是每个read,write都调用内核中的一个系统调用,数据直接在用户空间缓冲区和内核高速缓冲区之间复制
read()和write()系统调用在操作磁盘文件的时候不会直接发起磁盘访问,而是仅仅在用户空间缓冲区和内核缓冲区高速缓存之间复制数据,复制完毕,系统调用就会结束,然后就是内核自己解决数据在内核缓冲区到磁盘传递的问题
目的:使得I/O调用更加快速
与文件发生大量的数据传输的时候,尽量采用大的缓冲区数据据,以及执行更少的系统调用,可以大大提升I/O性能
write调用把用户空间缓冲区的数据复制到内核缓冲区之后,由内核在把数据写入到磁盘,如果此时其它进程访问该文件,那么内核会把内核缓冲区的数据传递给该进程
read系统调用从内核缓冲区读取数据的时候,会把缓冲区的数据读取大最大,读完之后,系统会把下一段的数据从磁盘都入到内核高速缓冲区
文件空洞:程序的偏移量跨越了文件结尾,read调用会返回0,write确可以在文件结尾后面的任意位置写入数据,在文件结尾这后面的一部分数据空间就叫做文件空洞,然而文件空洞不会占用磁盘空间,只有在文件空洞中写入了数据之后,系统才会为之分配空间
open调用中,参数O_CREAT和O_EXCL一般放在一起用,O_EXCL用来判断文件是否存在,在创建文件的时候,如果文件已经存在,那么open就会报错,如果不使用O_EXCL标记,就算文件存在,open调用创建文件的时候,open调用也会成功,这就导致,一个文件从属两个进程,这样是不对的,两个文件可以以一个写,另外一个读的方式打开同一个文件,但是不能同时创建文件,所以这也是参数O_CREAT和O_EXCL放在一起使用的原因,让一个文件以独占的方式被创建,两个标志在一起属于一个原子操作,是不能被打断的
fcntl函数,判断文件的访问模式的时候,只读、只写、可读可写,三个常量不与文件标志位的单个bit位对应,要判断其访问模式,需要把获取的flag和O_ACCMODE相与的结果在和O_RDWR这类的标记比较
可以使用fcntl修改的某些文件的标志位只有,O_APPEND、O_NONBLOCK、O_NOA
ti
ME、O_ASYNV、O_DIRECT,系统忽略其它标记的修改操作
fcntl尤其适用的场景:
文件不是由调用进程打开,比如标准输入、输出等
文件描述符通过open以外的系统调用打开,比如socket()、pipe()
fcntl使用举例:
2 文件I/O缓冲(标准I/O)
标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头文件中的定义,具有一定的可移植性。标准I/O库处理很多细节。例如缓存分配,以优化长度执行I/O等。标准的I/O提供了三种类型的缓存,相当于在文件I/O上又进行了一些封装
全缓存:当填满标准I/O缓存后才进行实际的I/O操作,例如磁盘块读写
行缓存:当输入或输出中遇到新的换行符时,标准I/O库执行I/O操作。
不带缓存:stderr就是了
标准I/O带缓冲的原因:使用标准I/O,比如fopen,会在调用的时候创建一个标准I/O缓冲区,当达到标准I/O的准则的时候,在把标准I/O缓冲区的数据写入到内核缓冲区中,所以在使用标准I/O的时候,有用户空间缓冲区,标准I/O缓冲区,内核数据高速缓冲区这几个个缓冲区
/**************************
函数功能:设置标准I/O的缓冲工作模式
返回值:The function setvbuf() returns 0 on success. It returns nonzero on
failure (mode is invalid or the request cannot be honored). It may set
errno on failure.
**************************/
#inclde
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
/*参数
stream:指代标准流,stdin、stdout、stderr
buf:保存了开辟的标准I/O缓冲区,设置为NULL的话,系统自动在内存中开辟一个标准I/O缓冲区
mode:标准I/O的工作模式
1.标准I/O不缓冲
2.采用行缓冲
3.采用全缓冲
size:标准I/O缓冲区大小,如果buf为NULL,size会被忽略
*/
/**************************
函数功能:强制把标准I/O缓冲区中的内容,刷新到内核缓冲区中
返回值:Upon successful completion 0 is returned. Otherwise, EOF is returned
and errno is set to indicate the error.
**************************/
#include
int fflush(FILE *stream);
/*参数:
stream指代标准流指针
*/
3 内核高速缓冲区的控制
同步I/O数据完整性:
对读操作来说:意味着被请求的文件数据已经从磁盘传递到进程
对写操作而言:文件数据已经传递到磁盘,但是某些文件元数据就算被修改了,比如文件的时间戳,如果没有写入磁盘,也满足数据完整性
同步I/O文件完整性:是同步I/O数据完整性的超集,此时元数据也是考虑的因素之一,才能保证同步I/O文件完整性
如果open调用指定了O_SYNC标志,那么write调用会直接把用户空间的数据直接刷新到磁盘中,而不会复制到内核缓冲区,但是尽量不使用这个标志,原因如下图:
缓冲示意图:
更多回帖
rotate(-90deg);
回复
相关帖子
文件IO
缓冲
LabVIEW
文件
IO
21
3.3.1
IO
文件
汇总
8
LabVIEW
文件
IO
0
数据存储与
文件
IO
0
飞凌嵌入式ElfBoard-标准
IO
接口
之
设置
缓冲
区
1208
飞凌嵌入式ElfBoard-标准
IO
接口
之
刷新
缓冲
1079
飞凌嵌入式ElfBoard-系统
IO
接口
之
刷新内核
缓冲
1506
嵌入式Linux开发系统开发
之
《一节课搞懂
文件
IO
与标准
IO
》
10
文件
IO
操作时的常见错误
1987
AUTOSAR BSW
之
IO
概述
2422
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
首页
论坛版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分