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缓冲区相关推荐
- linux文件IO与内存映射:分散/聚集IO技术(scatter-gather)
前言 根据上文我们学习到的用户空间的IO缓冲区,操作系统为了减少系统调用的次数,节省系统开销,提出了用户空间的IO缓冲区,即为用户空间的文件读写开辟一段可以利用setvbuf配置大小的内存空间来作为文 ...
- linux 文件IO与内存映射:内存映射
前言 前面几篇我们学习了用户空间的IO缓冲区,以及IO缓冲区的分散聚合IO技术. 为了减少系统调用的次数,提升系统性能,操作系统开发者门提出了这么多的缓存技术. 但是到这里这些技术同样有不足的地方:不 ...
- Linux内核源码分析—从用户空间复制数据到内核空间
Linux内核源码分析-从用户空间复制数据到内核空间 本文主要参考<深入理解Linux内核>,结合2.6.11.1版的内核代码,分析从用户空间复制数据到内核空间函数. 1.不描述内核同步. ...
- 浅谈Java堆内内存、堆外内存、直接内存、用户空间和内核空间
我们都知道Java中大多数的对象都存在于堆内存中,那什么是堆外内存.直接内存?它们又分别用来做什么?分布在用户空间还是内核空间? 首先,有个前置知识点,所谓的Java程序,其实可以理解为是用C/C++ ...
- 磁盘IO:缓存IO、直接IO、内存映射
磁盘IO的几种访问方式如下: 缓存IO 缓存I/O又被称作标准I/O,大多数文件系统的默认I/O操作都是缓存I/O.在Linux的缓存I/O机制中,数据先从磁盘复制到内核空间的缓冲区,然后从内核空间缓 ...
- linux usb ga驱动详解,Linux设备驱动之内存映射
1. 内存映射 所谓的内存映射就是把物理内存映射到进程的地址空间之内,这些应用程序就可以直接使用输入输出的地址空间,从而提高读写的效率.Linux提供了mmap()函数,用来映射物理内存. 在驱动程序 ...
- C语言读取大文件的问题 内存映射
2019独角兽企业重金招聘Python工程师标准>>> [Ref] Windows对文件的读写提供了很丰富的操作手段,如: 1. FILE *fp, fstearm...; (C/C ...
- linux设备驱动开发之udev用户空间设备管理
什么是udev? 这章我们来讨论一下udev这个玩意.它是什么呢?我们可以看下它的使用文档: NAME// udev-动态设备的管理功能udev - Dynamic device management ...
- linux平台驱动运行空间,UIO(linux Userspace I/O子系统)用户空间设备驱动I/O技术介绍...
UIO(linux Userspace I/O子系统)用户空间设备驱动I/O技术介绍(由搜集整理) UIO(Userspace I/O)是运行在用户空间的I/O技术.Linux系统中一般的驱动设备都是 ...
最新文章
- oracle 11g goldengate DML单向复制测试环境搭建
- 022_jdbc-mysql封装JDBCUtil和抽取数据库配置参数文件
- c/c++的typedef/using类型别名
- professor‘s great paper in multi agent system
- js函数中参数的传递
- FPGA 资料搜集记录
- NSARRAY的 内存管理
- 计算机网络硬件脆弱性,计算机网络的脆弱性有哪几点
- mysql json字段的使用与意义
- swagger文档配置
- 网络爬虫之手机号测吉凶(纯属娱乐)
- Bandicam v5.2.1.1860 班迪录屏绿色便携版
- 必收藏的九大塑料注塑成型技术及其特点
- ios10--拳皇动画
- 对象存储s3cmd使用手册
- 聚宽macd底背离_MACD背离技术分析(图解)
- 吴军《智能时代》读书笔记
- EMCC Vmware 安装82%出错
- 社会实践论文关于计算机网络,计算机社会实践毕业论文题目大全 计算机社会实践专业论文题目怎样拟...
- 层次聚类sklearn.cluster包AgglomerativeClustering
热门文章
- eclipse调用JNI之环境的搭建
- Android 高清加载巨图方案 拒绝压缩图片
- 调用bat文件执行java文件
- 移动应用开发—— 如何搭建开发大型的应用架构?
- Unity3D中的函数方法及解释
- token验证失败_ASP.NET CORE WEBAPI JWT 带BEARER的TOKEN
- android+图标闪烁动画,如何在android中闪烁通知图标? [DONE]
- vuex的命名空间有哪些_专业餐饮全案策划设计公司报价?具体做哪些服务?
- linux系统分析命令,Linux操作系统基础解析之(四)——Linux基本命令剖析(2)
- linux内核添加c代码,如何从C代码加载Linux内核模块?