文章目录

  • 用户空间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
};

其中重要的数据结构为:

  1. int _fileno;我们的文件描述符
  2. char *_IO_buf_base; IO缓冲区的起始区域
  3. 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缓冲区相关推荐

  1. linux文件IO与内存映射:分散/聚集IO技术(scatter-gather)

    前言 根据上文我们学习到的用户空间的IO缓冲区,操作系统为了减少系统调用的次数,节省系统开销,提出了用户空间的IO缓冲区,即为用户空间的文件读写开辟一段可以利用setvbuf配置大小的内存空间来作为文 ...

  2. linux 文件IO与内存映射:内存映射

    前言 前面几篇我们学习了用户空间的IO缓冲区,以及IO缓冲区的分散聚合IO技术. 为了减少系统调用的次数,提升系统性能,操作系统开发者门提出了这么多的缓存技术. 但是到这里这些技术同样有不足的地方:不 ...

  3. Linux内核源码分析—从用户空间复制数据到内核空间

    Linux内核源码分析-从用户空间复制数据到内核空间 本文主要参考<深入理解Linux内核>,结合2.6.11.1版的内核代码,分析从用户空间复制数据到内核空间函数. 1.不描述内核同步. ...

  4. 浅谈Java堆内内存、堆外内存、直接内存、用户空间和内核空间

    我们都知道Java中大多数的对象都存在于堆内存中,那什么是堆外内存.直接内存?它们又分别用来做什么?分布在用户空间还是内核空间? 首先,有个前置知识点,所谓的Java程序,其实可以理解为是用C/C++ ...

  5. 磁盘IO:缓存IO、直接IO、内存映射

    磁盘IO的几种访问方式如下: 缓存IO 缓存I/O又被称作标准I/O,大多数文件系统的默认I/O操作都是缓存I/O.在Linux的缓存I/O机制中,数据先从磁盘复制到内核空间的缓冲区,然后从内核空间缓 ...

  6. linux usb ga驱动详解,Linux设备驱动之内存映射

    1. 内存映射 所谓的内存映射就是把物理内存映射到进程的地址空间之内,这些应用程序就可以直接使用输入输出的地址空间,从而提高读写的效率.Linux提供了mmap()函数,用来映射物理内存. 在驱动程序 ...

  7. C语言读取大文件的问题 内存映射

    2019独角兽企业重金招聘Python工程师标准>>> [Ref] Windows对文件的读写提供了很丰富的操作手段,如: 1. FILE *fp, fstearm...; (C/C ...

  8. linux设备驱动开发之udev用户空间设备管理

    什么是udev? 这章我们来讨论一下udev这个玩意.它是什么呢?我们可以看下它的使用文档: NAME// udev-动态设备的管理功能udev - Dynamic device management ...

  9. linux平台驱动运行空间,UIO(linux Userspace I/O子系统)用户空间设备驱动I/O技术介绍...

    UIO(linux Userspace I/O子系统)用户空间设备驱动I/O技术介绍(由搜集整理) UIO(Userspace I/O)是运行在用户空间的I/O技术.Linux系统中一般的驱动设备都是 ...

最新文章

  1. oracle 11g goldengate DML单向复制测试环境搭建
  2. 022_jdbc-mysql封装JDBCUtil和抽取数据库配置参数文件
  3. c/c++的typedef/using类型别名
  4. professor‘s great paper in multi agent system
  5. js函数中参数的传递
  6. FPGA 资料搜集记录
  7. NSARRAY的 内存管理
  8. 计算机网络硬件脆弱性,计算机网络的脆弱性有哪几点
  9. mysql json字段的使用与意义
  10. swagger文档配置
  11. 网络爬虫之手机号测吉凶(纯属娱乐)
  12. Bandicam v5.2.1.1860 班迪录屏绿色便携版
  13. 必收藏的九大塑料注塑成型技术及其特点
  14. ios10--拳皇动画
  15. 对象存储s3cmd使用手册
  16. 聚宽macd底背离_MACD背离技术分析(图解)
  17. 吴军《智能时代》读书笔记
  18. EMCC Vmware 安装82%出错
  19. 社会实践论文关于计算机网络,计算机社会实践毕业论文题目大全 计算机社会实践专业论文题目怎样拟...
  20. 层次聚类sklearn.cluster包AgglomerativeClustering

热门文章

  1. eclipse调用JNI之环境的搭建
  2. Android 高清加载巨图方案 拒绝压缩图片
  3. 调用bat文件执行java文件
  4. 移动应用开发—— 如何搭建开发大型的应用架构?
  5. Unity3D中的函数方法及解释
  6. token验证失败_ASP.NET CORE WEBAPI JWT 带BEARER的TOKEN
  7. android+图标闪烁动画,如何在android中闪烁通知图标? [DONE]
  8. vuex的命名空间有哪些_专业餐饮全案策划设计公司报价?具体做哪些服务?
  9. linux系统分析命令,Linux操作系统基础解析之(四)——Linux基本命令剖析(2)
  10. linux内核添加c代码,如何从C代码加载Linux内核模块?