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。

函数功能:主要用于调整文件的读写位置。

注意:

文件的末尾位置指的是文件中最后一个字符的下一个位置。

回避现实的人,未来将更不理想。

linux下的文件IO缓冲区,及其相关操作

相关文章:

你感兴趣的文章:

标签云: