linux下的文件IO缓冲区,及其相关操作
linux下的文件IO操作
浅谈文件IO缓冲
Read()和write()函数在操作磁盘文件时不会直接发起磁盘访问,而是仅仅在用户空间缓冲区与内核缓冲区高速缓存之间复制数据。
当调用write()函数的写入3个字节的时候,由于系统调用与磁盘操作并不同步,在write()函数结束后续某个时刻,内核才会将其缓冲区中的数据写入磁盘。如果在此期间,另一个进程试图读取该文件的这几个字节,那么内核将自动从缓冲区高速缓存中提供这些数据,而不是文件中。
与此同理,对输入而言,内核从磁盘中读取数据并存储到内核缓冲区中。Read()调用将从该缓冲区中读取数据,直至把缓冲区中的数据取完,这时,内核会将文件的下一段内容读入缓冲区高速缓存。
采用这一设计,目的是令read()和write()调用的操作更为快速,因为它们不需要等待磁盘操作。同时,这一设计也极为高效,因为这减少了内核必须执行的磁盘传输次数。
Linux内核对缓冲区高速缓存的大小没有固定上限。内核会分配尽可能多的缓冲区高速缓存页,而仅受限于两个因素:可用的物理内存总量,以及出于其他目的对物理内存的需求。若可用内存不足,则内核会将一些修改过的缓冲区高速缓存页刷新到磁盘,并释放其供系统重用。
缓冲区大小对IO系统调用性能的影响
在磁盘上写1000个字节,无论是每次写一个字节还是一次写入1000个字节,内核访问磁盘的次数都是相同的。但是前者的所消耗的时间明显比后者要多,后者只需要一次系统调用,而前者需要调用1000次。
在使用write函数和read函数的时候,我们可以定义一个缓冲区,一个大小适中的缓冲区能大大增加读写的效率,缓冲区的大小可以按照实际情况而定。相比之下,stdio中的IO操作由于fwrite函数和fread函数中已经有自己的缓冲区了,write函数和read函数使用起来更灵活。
1 文件的基本概念
在Unix/linux系统中,几乎所有的一切都可以看作文件,因此对于文件的操作适用于各种输入输出设备等等,当然目录也可以看作文件。
如:
文件相关的读写函数
(1)open函数
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode)
以第二个open函数为例,解析如下:
第一个参数:字符串形式的文件路径和文件名
第二个参数:操作标志
必须包含以下访问模式中的一种:
O_RDONLY- 只读
O_WRONLY- 只写
O_RDWR - 可读可写
还可以按位或一下的标志值
O_APPEND- 追加,写入到文件的尾部
O_CREAT - 文件不存在则创建,存在则打开
O_EXCL - 与O_CREAT搭配使用,如果文件存在则open失败
O_TRUNC - 文件存在且允许写,则清空文件
第三个参数:操作模式,权限
当创建新文件时,需要指定的文件权限
如:
0644=> rw-r--r--
返回值:成功返回新的文件描述符(非负整数),失败返回-1
函数功能:主要用于 打开/创建一个 文件/设备
(2)close函数
#include <unistd.h>
int close(int fd);
返回值:成功返回0,失败返回-1。
函数功能:
主要用于关闭参数fd指定的文件描述符,也就是让描述符fd不再关联任何一个文件,以便于下次使用。
(3)read函数
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
第一个参数:文件描述符(从哪里读)
第二个参数:缓冲区的首地址(存到哪里去)
第三个参数:读取的数据大小
返回值:成功返回读取到的字节数,返回0表示读取到文件尾
失败返回-1
函数功能:表示从指定的文件中读取指定大小的数据
(4)write函数
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
第一个参数:文件描述符(写入到哪里去)
第二个参数:缓冲区的首地址(数据从哪里来)
第三个参数:要写入的数据大小
返回值:成功返回写入的字节数,返回0表示没有写入
失败返回-1
函数功能:表示将指定的数据写入到指定的文件中。
注意:
read和write函数一般默认以二进制形式进行读写。
(5)lseek函数
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
第一个参数:文件描述符(表示在哪个文件中操作)
第二个参数:偏移量(正数表示向后偏移,负数向前偏移)
第三个参数:起始位置(从什么地方开始偏移)
SEEK_SET- 文件开头位置
SEEK_CUR- 文件当前位置
SEEK_END- 文件结尾位置
返回值:成功返回距离文件头的偏移量,失败返回-1。
函数功能:主要用于调整文件的读写位置。
注意:
文件的末尾位置指的是文件中最后一个字符的下一个位置。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。