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

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
};

其中重要的数据结构为:

  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库函数:

  • 头文件
  • 函数使用:
    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 int main() { char buf[BUFSIZ];char buf2[BUFSIZ];//printf("BUFSIZ is %d
",BUFSIZ);setvbuf(stdout,buf,_IOFBF,BUFSIZ);printf("BUFSIZ after setvbuf is %d
",BUFSIZ);setbuffer(stdout, buf2,10240);printf("hello world
");printf("buf:%s
",buf);printf("buf2:%s
",buf2);return 0;
}

更多相关:

  • 文章目录先看看性能AIO 的基本实现io_ring 使用io_uring 基本接口liburing 的使用io_uring 非poll 模式下 的实现io_uring poll模式下的实现io_uring 在 rocksdb 中的应用总结参考...

  • 串口发送部分代码: //通过信号量的方法发送数据 void usart1SendData(CPU_INT08U ch) {OS_ERR err;CPU_INT08U isTheFirstCh;OSSemPend(&Usart1Sem, 0, OS_OPT_PEND_BLOCKING, NULL, &err);//阻塞型等待串口发送资...

  • 本文来自 运维人生 ,作者:fly是个稻草人链接:http://www.ywadmin.com/?id=76误删除linux系统文件了?不用急,本文将给你一个恢复linux文件的方法,让你轻松应对运维中的各风险问题。方法总比问题多~说在前面的话针对日常维护操作,难免会出现文件误删除的操作。大家熟知linux文件系统不同win有回收...

  • 原文来自SecIN社区—作者:WiHat0x00 什么是WebShell渗透测试工作的一个阶段性目标就是获取目标服务器的操作控制权限,于是WebShell便应运而生。Webshell中的WEB就是web服务,shell就是管理攻击者与操作系统之间的交互。Webshell被称为攻击者通过Web服务器端口对Web服务器有一定的操作权限,而...

  • 断电时文件系统发生了什么?硬盘又发生了什么?下一次开机时写到一半的文件在系统层面还在吗?在底层还在吗?更进一步的, 文件系统如何保证事务性, 会不会存在某种极端情况导致例如最后几个bit还没写完, 文件系统却认为它成功了的情况?回答不限任何文件系统,谢谢!下面是「北极」的回复分享断电的一瞬间,很多事情是无法确定的:1. 你无法确定...

  • 接到项目需求。需要搭建一个页面进行交互,慢慢来b (2).jpg使用python django框架进行页面的搭建在项目文件下打开窗口,输入命令;django-admin startproject helloword#在文件helloword/helloword/创建view.py在view.py文件中输入以代码from django....

  • 常见的错误集合解决方案(一)No.1提示错误'Microsoft.VC90.CRT,version="9.0.21022.8"把Microsoft.NET Framework 3.5.1下面的全部勾选上。No.2解决Qt Designer设计的图标但是VS生成不显示问题描述:在Qt designer中为菜单栏和工具栏设计的图标,但是...