失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > linux文件IO与内存映射:用户空间的IO缓冲区

linux文件IO与内存映射:用户空间的IO缓冲区

时间:2021-04-12 17:15:04

相关推荐

linux文件IO与内存映射:用户空间的IO缓冲区

文章目录

用户空间IO缓冲区产生IO缓冲区 描述IO缓冲区的写模式自定义IO缓冲区

用户空间IO缓冲区产生

系统调用过程中会产生的开销如下:

切换CPU到内核态进行数据内容的拷贝,从用户态到内核态或者从内核态到用户态切换CPU到用户态

以上为普通到系统调用过程中操作系统需要产生的额外开销,为了提升系统调用的性能,这里推出用户空间的IO缓冲区,即文件读写在用户空间时写入IO缓冲区,后续的写入或者读出page cache则直接由IO缓冲区进行读写。

IO缓冲区所处操作系统位置如下图:

IO缓冲区 描述

C标准库创建的IO缓冲区

在用户空间,为每个打开的文件分配一个I/O缓冲区、分配一个文件描述符、I/O缓冲区信息和文件描述符一起封装在FIFE结构体中size_t fread(void *ptr,size_t size,size_t memb,FILE *stream);size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

关于FILE结构体的内容如下/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h

/* The tag name of this struct is _IO_FILE to preserve historicC++ mangled names for functions taking FILE* arguments.That name should not be used in new code. */struct _IO_FILE{int _flags;/* High-order word is _IO_MAGIC; rest is flags. *//* The following pointers correspond to the C++ streambuf protocol. */char *_IO_read_ptr;/* Current read pointer */char *_IO_read_end;/* End of get area. */char *_IO_read_base;/* Start of putback+get area. */char *_IO_write_base;/* Start of put area. */char *_IO_write_ptr;/* Current put pointer. */char *_IO_write_end;/* End of put area. */char *_IO_buf_base;/* Start of reserve area. */char *_IO_buf_end;/* End of reserve area. *//* The following fields are used to support backing up and undo. */char *_IO_save_base; /* Pointer to start of non-current get area. */char *_IO_backup_base; /* Pointer to first valid character of backup area */char *_IO_save_end; /* Pointer to end of non-current get area. */struct _IO_marker *_markers;struct _IO_FILE *_chain;int _fileno;int _flags2;__off_t _old_offset; /* This used to be _offset but it's too small. *//* 1+column number of pbase(); 0 is unknown. */unsigned short _cur_column;signed char _vtable_offset;char _shortbuf[1];_IO_lock_t *_lock;#ifdef _IO_USE_OLD_IO_FILE};

其中重要的数据结构为:

int _fileno;我们的文件描述符char *_IO_buf_base;IO缓冲区的起始区域char *_IO_buf_end;IO缓冲区的结束区域

当使用fread进行读文件时

打开文件,获取到文件描述符_fileno利用文件描述符获取到文件inode,根据文件inode先到io缓冲区中获取当前文件内容,如果获取不到则执行下一步,否则直接返回。根据文件inode从page cache中获取到对应的缓存页的内容将获取到的内容读到读的IO缓冲区

当使用fwrite写文件时

打开文件,获取到文件描述符利用文件描述符获取到文件inode,将需要写到内容写入到io缓冲区中io缓冲区利用fflush将其中到内容写入到page cache页高速缓冲区中再由page cache根据是否达到阈值,将page cache中的数据pdflush回写到磁盘中

IO缓冲区的写模式

使用fwrite写文件时的第二步 IO 缓冲区中的数据fflush到page cache时有几种不同的写模式,即根据不同的模式将IO缓冲区的数据写入到page cache中。

块缓冲(block buffered):

固定字节的缓冲区大小,比如跟文件相关的流都是块缓冲

标准IO块缓冲为完全缓冲(full bufferring)

此时,当客户端将块缓冲区写满之后,才会向page cache中下刷数据,一般的文件操作都为块缓冲区行缓冲(line buffered):

遇到换行符,缓冲区中的数据会拷贝到内核缓冲区无缓冲(unbuffered)

数据直接拷贝到内核缓冲区

如:标准错误stderr采用无缓冲模式

自定义IO缓冲区

系统默认开辟的IO缓冲区大小为8K,但是很多时候我们需要写入文件内容是大于8K,这个时候需要我们自定义IO缓冲区大小,使用如下C库函数:

头文件<stdio.h>函数使用:

void setbuf(FILE *stream, char *buf); //无缓冲区void setbuffer(FILE *stream, char *buf, size_t size);//块缓冲区void setlinebuf(FILE *stream);//行缓冲区//兼容三种缓冲期int setvbuf(FILE *stream, char *buf, int mode, size_t size);

参数描述:stream指向流的指针buf缓冲区地址mode缓冲区类型

如下三种

_IONBF //无unbuffered_IOLBF //行line buffered_IOFBF //块fully buffered

size缓冲区内字节数

代码如下:

#include <stdio.h>int main() {char buf[BUFSIZ];char buf2[BUFSIZ];//printf("BUFSIZ is %d\n",BUFSIZ);setvbuf(stdout,buf,_IOFBF,BUFSIZ);printf("BUFSIZ after setvbuf is %d\n",BUFSIZ);setbuffer(stdout, buf2,10240);printf("hello world\n");printf("buf:%s\n",buf);printf("buf2:%s\n",buf2);return 0;}

如果觉得《linux文件IO与内存映射:用户空间的IO缓冲区》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。