linux系统io错误,linux系统IO操作

本文重点说明下面内容:

什么是标准IO,什么是文件IO?

什么是Direct IO? O_SYNC标识有什么意义?

各个层面的缓存如何同步?

还在page cache中的脏页可以读写吗?

IO路径上的各层buff

Application buff

|

clib buff

|

page cache

|

disk cache

标准IO

标准IO操作的是流(File对象)

标准IO可以设置缓存,这个缓存是用户态buffer,一般称为clib buff

api

#include

//打开流

FILE *fopen(const char *pathname, const char *type);

//关闭流

int fclose(File *fp);

// 刷新流

int fflush(FILE *fp);

// 一次读写一个字符

int fgetc(FILE *fp);

int fputc(FILE *fp);

// 一次读写一行

char* fgets(char* buf, int n, FILE* fp);

int fputs(const char *str, FILE* fp);

// 二进制读写

size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp);

size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp);

// 格式化输入输出

int fprintf(FILE *fp, const char* format, ...);

int fscanf(FILE *fp, const char *format, ...);

// 示例

#include

#include

int main(void){

char buf[1024];

while (fgets(buf, 1024, stdin) != NULL)

if (fputs(buf, stdout) == EOF)

printf("output error");

if (ferror(stdin))

printf("input error");

exit(0);

}

说明

调用fwrite, fputc, fputs系列函数后,数据被保存到clib buf中,依然处于用户态,如果此时应用进程crash掉,这些数据将丢失。

在调用fflush可将clib buf中的数据写入内核的page cache中。

调用fclose也会将clib buff中的数据刷新到内核,并且把clib buff中的输入数据丢弃。

从这些标准IO的API可看出,标准IO比文件IO要简洁很多,没有各种标识,没有sync, nonblock等。

上列API具体使用细节可参考《unix环境高级编程》第5章。

文件IO

文件IO是直接操作linux系统调用,大部分的问题都是使用文件IO带来的。

api

int open(const char *pathname, int oflag);

int close(int filedes);

ssize_t read(int filedes, void* buff, size_t nbytes);

ssize_t write(int filedes, const void* buff, size_t nbytes);

int fsync(int filedes);

int fcntl(int filedes, int cmd);

int ioctl(int filedes, int request);

说明

O_SYNC标识打开的文件,会在write系统调用时,会等待IO从底层返回;O_SYNC仅对写有意义。

O_DIRECT标识打开的文件不经过page cache; O_DIRECT对读写都是有意义的。

O_NONBLOCK标识打开的文件(一般是网络IO,终端设备IO) ,在不可读写时立即返回EAGAIN等错误码。

O_SYNC, O_DIRECT有区别如下,

size_t wirte_file()

{

if(o_DIRECT)

direct_io();

else

buffered_io();

if( O_SYNC )

wait_data_synced();

}

上述API细节可参考《unix环境高级编程》第3章。

mmap

api

#include

void *mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset);

mmap在calling process的虚拟地址空间中创建一个映射,主要有以下两种常用方式:

对文件创建一个mapping,读写文件可以用读写内存替代。

匿名映射,传入的fd为-1

创建mapping后,省掉了数据从在用户态buff和内核page cache的拷贝

后续整理下linux系统文件IO流程

你可能感兴趣的:(linux系统io错误)