缓冲区:
- 缓冲区是一块内存区域,用于存储数据,直到数据被真正写入到文件或设备中,或从文件或设备中读取。
- 这种机制使得程序可以一次处理较大的数据块,而不是频繁地进行较小的I/O操作。
缓冲模式:
- 全缓冲:数据会被先写入缓冲区,直到缓冲区满了才会实际写入到文件中。这种模式通常用于文件。
- 行缓冲:数据会在遇到换行符时被写入到文件中。行缓冲通常用于终端设备。
- 无缓冲:数据每次调用
read
或write
时都会直接进行操作,没有缓冲区。这种模式适用于需要实时数据处理的设备。
标准IO函数:
fopen()
,fread()
,fwrite()
,fclose()
:用于打开文件、读取数据、写入数据和关闭文件。fflush()
:用于强制将缓冲区的数据写入到文件中。这在需要确保数据被写入时特别有
缓冲区刷新时机:
- 自动刷新:当缓冲区满了、遇到换行符(对于行缓冲模式)或关闭文件时,标准IO库会自动刷新缓冲区。
- 显式刷新:通过调用
fflush()
函数,程序可以显式地刷新指定流的缓冲区。
标准IO和系统调用的区别
-
标准I/O(
stdio
):- 接口:提供了更高层次的文件操作接口,如
fopen()
,fread()
,fwrite()
,fclose()
等。 - 缓冲:标准I/O库使用缓冲区来提高I/O效率。例如,
fread()
和fwrite()
操作会在缓冲区中进行,只有在缓冲区满了或流被关闭时才会实际读写数据。 - 便捷性:提供了文件流的抽象,便于进行格式化输入输出(如
fprintf()
和fscanf()
),并处理文件位置指针等。
- 接口:提供了更高层次的文件操作接口,如
-
系统调用:
- 接口:提供了底层的文件操作接口,如
open()
,read()
,write()
,close()
等。 - 无缓冲:系统调用直接与操作系统交互,没有标准I/O库中的缓冲机制。每次
read()
或write()
调用都直接操作文件描述符。 - 控制:允许更细粒度的控制和操作,比如文件的权限设置、文件描述符的操作等。
- 接口:提供了底层的文件操作接口,如
系统调用列表:
open()
:打开一个文件或设备,返回一个文件描述符。可以设置文件打开模式和权限。read()
:从文件描述符中读取数据。需要指定要读取的字节数。write()
:向文件描述符中写入数据。需要指定要写入的数据和字节数。close()
:关闭一个文件描述符,释放相关资源。lseek()
:改变文件描述符的文件偏移量,支持随机访问。
特点:
- 直接操作:系统调用提供直接的文件描述符操作,不经过标准I/O库的缓冲区机制,通常用于需要更高性能或特殊控制的场景。
- 文件描述符:每个打开的文件、设备或管道都有一个唯一的文件描述符(整数)。这些文件描述符是系统调用操作的基础。
- 底层控制:系统调用允许进行底层操作,比如设置文件状态标志(如
O_NONBLOCK
)、文件锁等。 - 无缓冲:每次
read()
和write()
操作都直接访问内核和文件系统,这意味着可以精确控制I/O操作,但也可能需要更多的处理来管理数据的读写。 - 性能:由于系统调用直接操作底层文件描述符,通常可以获得更高的性能,但编程时需要管理更多的细节。
Linux系统调用中常用文件I/O函数的详细讲解:
1. open()
作用:打开一个文件或设备,并返回一个文件描述符,用于后续的读写操作。
原型:
int open(const char *pathname, int flags, mode_t mode);
pathname
:要打开的文件或设备的路径。flags
:指定打开文件的模式(如只读、只写、读写等)。常见标志包括:O_RDONLY
:只读模式O_WRONLY
:只写模式O_RDWR
:读写模式O_CREAT
:如果文件不存在,则创建新文件O_TRUNC
:如果文件存在,则截断文件长度为0O_APPEND
:每次写入时,追加到文件末尾
mode
(可选):文件权限模式,仅在O_CREAT
标志被使用时需要。常用的权限模式包括:S_IRUSR
:所有者可读S_IWUSR
:所有者可写S_IXUSR
:所有者可执行S_IRGRP
:组用户可读S_IWGRP
:组用户可写
- 成功时,返回一个非负整数,作为文件描述符。
- 失败时,返回
-1
,并设置errno
以指示错误原因。
2. read()
作用:从文件描述符中读取数据。
原型:
ssize_t read(int fd, void *buf, size_t count);
fd
:文件描述符,表示打开的文件或设备。buf
:指向存储读取数据的缓冲区的指针。count
:要读取的字节数。
返回值:
- 成功时,返回实际读取的字节数。如果文件末尾被达到了,返回
0
。 - 失败时,返回
-1
,并设置errno
以指示错误原因。
3. write()
作用:向文件描述符中写入数据。
原型:
ssize_t write(int fd, const void *buf, size_t count);
fd
:文件描述符,表示打开的文件或设备。buf
:指向要写入数据的缓冲区的指针。count
:要写入的字节数。
返回值:
- 成功时,返回实际写入的字节数。
- 失败时,返回
-1
,并设置errno
以指示错误原因。
4. close()
作用:关闭一个文件描述符,释放相关资源。
原型:
int close(int fd);
fd
:要关闭的文件描述符。
返回值:
- 成功时,返回
0
。 - 失败时,返回
-1
,并设置errno
以指示错误原因。
5. lseek()
作用:改变文件描述符的文件偏移量,支持随机访问。
原型:
off_t lseek(int fd, off_t offset, int whence);
fd
:文件描述符。offset
:相对于whence
的位置的偏移量。whence
:指定偏移量的基准点,常用值包括:SEEK_SET
:从文件开始处SEEK_CUR
:从当前位置SEEK_END
:从文件末尾
返回值:
- 成功时,返回新的文件偏移量。
- 失败时,返回
-1
,并设置errno
以指示错误原因。
笔记详解