e## 内核缓冲:缓冲区高速缓存
read()和write()系统调用在操作磁盘文件时不会直接发起磁盘访问,而仅仅在用户空间缓冲区和内核缓冲区高速缓存之间复制数据。例如
write(fd, "abc", 3);
write会立即返回。在后续某个时刻,内核会将其缓冲区中的数据写入磁盘。在此期间,另一进程试图读取该文件的这几个字节,那么内核将会自动从缓冲区高速缓存中提供。
stdio库缓冲
设置一个stdio流的缓冲模式
#include<stdio.h>
int setvbuf(FILE* stream, char* buf, int mode, size_t size);
打开流之后,必须在调用其他stdio函数之前先调用setvbuf。
参数buf和size针对要使用的缓冲区
如果buf不为NULL,则指向以size大小的内存块。(应使用堆中内存)
如果buf为NULL,stdio会自动分配缓冲区
mode:
_IONBF:
不对I/O进行缓冲。即 立即调用write,read
_IOLBF:
采用行缓冲。对于输出流,在输出一个换行符(除非缓冲区满)前将缓冲数据。对于输入流,每次读一行。
_IOFBF:
全缓冲。单次读写数据的大小与缓冲区相同。
#include<stdio.h>
void setbuf(FILE* stream, char* buf);
该函数等于:
setvbuf(fp, buf, (buf != NULL) ? _IOFBF: _INOBF, BUFSIZE);
刷新stdio缓冲区
int fflush(FILE* stream);
若参数为NULL,则刷新所有的缓冲区。
控制文件IO的内核缓冲
同步IO完成:某一IO操作,要么已成功完成到磁盘的数据传递,要么被诊断为不成功。
同步IO数据完整性:确保针对文件的一次更新传递了足够的信息到磁盘,以便于之后对数据的获取。
同步IO文件完整性:在对文件更新过程中,要将所有发生更新的文件元数据都传递到磁盘上。
#include<unistd.h>
int fsync(int fd);
fsync会强制文件处于同步IO文件完整性。
#include<unistd.h>
int fdatasync(int fd);
例:若修改了文件数据,但是文件大小不变,那么调用fdatasync()只强制进行了数据更新。而fsync会将元数据页传递到磁盘上。
使所有写入同步:O_SYNC
调用open函数时加上O_SYNC,会使后续所有输出同步
int fd = open(name, O_WRONLY|O_SYNC);
调用open后write会按同步IO文件完整的要求执行。
混合使用库函数和系统调用进行文件IO
#include<stdio.h>
int fileno(FILE* stream);
FILE* fdopen(int fd, const char* mode);
IO系统调用会直接将数据传递到内核缓冲区高速缓存,而stdio库函数会等到用户空间流缓冲区满,在调用write。
《Linux/Unix 系统编程手册》