前言

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


描述

为了在以上IO缓冲区的基础上更进一步得减少系统调用的次数,提出了分散/聚合IO技术,总体上是使用了单个向量的IO操作代替了多个向量的IO操作。
读文多个件的时候将从page cache中读到的内容先读入到一个IO缓冲区数据结构中,再由一个缓冲区分别分散返回到多个文件缓冲区中;写文件的过程与读文件的过程刚好相反,即将多个文件缓冲区的内容聚合写到一个缓冲区中,写入page cache中,从而更高得提升系统调用效率。

实现

实现scatter-gather技术的系统调用原型如下:

  • 头文件<sys/uio.h>

  • 函数使用:
    ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
    ssize_t writev(int fd, const struct iovec *iov, int iovcnt);

  • 函数参数
    fd :打开的文件描述符
    iov: IO向量数据结构内容如下,每个结构体成员代表一个buffer:

     struct iovec {void  *iov_base;    /* Starting address */size_t iov_len;     /* Number of bytes to transfer */};
    

    iovcnt:IO向量的个数

    这两个系统调用的底层仍然是使用read/write系统调用,只是对IO 缓冲区做了聚合,支持多个IO缓冲区内容聚合到同一个IO向量中

代码如下:
writev.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/uio.h>
#include <fcntl.h>int main(int argc, char *argv[])
{ssize_t count = 0;int fd, i = 0;char *buf[]={"buffer1\n","buffer2\n","buffer3\n"};fd = open(argv[1], O_WRONLY|O_CREAT, 0666);if (-1 == fd) {printf("open failed \n");_exit(-1);}//将三个IO缓冲区的文件聚合为一个IO向量struct iovec iov[3];for (i ; i < 3; ++i) {iov[i].iov_base = buf[i];iov[i].iov_len = sizeof(buf[i]) + 1;printf("iovec[%d] size is %ld \n",i,iov[i].iov_len);}//写入一个文件count = writev(fd, iov, 3);if (-1 == count) {printf("writev failed\n");_exit(-1);}close(fd);return 0;
}

readv.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/uio.h>
#include <fcntl.h>int main(int argc, char *argv[])
{ssize_t count = 0;int fd, i = 0;char buf1[9],buf2[9],buf3[9];//生成一个文件,可以传入聚合IO缓冲区的文件fd = open(argv[1], O_RDONLY,0666);if (-1 == fd) {printf("open failed \n");_exit(-1);}//对IO向量中的各个IO缓冲区进行地址和内容大小赋值struct iovec iov[3];iov[0].iov_base = buf1;iov[0].iov_len = sizeof(buf1);  iov[1].iov_base = buf2;iov[1].iov_len = sizeof(buf2); iov[2].iov_base = buf3;iov[2].iov_len = sizeof(buf3); //从page cache读入的一个向量会分散到三个缓冲区中count = readv(fd,iov,3);if (-1 == count) {printf("writev failed\n");_exit(-1);}for (i ; i < 3; ++i) {printf(" %s",(char *)(iov[i].iov_base));}prinft("buf1 %s\n",buf1);prinft("buf2 %s\n",buf2);prinft("buf3 %s\n",buf3);close(fd);return 0;
}

编译输出如下:
gcc writev.c -o writev
gcc readv.c -o readv

zhang@ubuntu:~/Desktop/cpp_practice$ ./writev  writevfile
iovec[0] size is 9
iovec[1] size is 9
iovec[2] size is 9
zhang@ubuntu:~/Desktop/cpp_practice$ ./readv writevfile buffer1buffer2buffer3
buf1 buffer1buf2 buffer2buf3 buffer3

linux文件IO与内存映射:分散/聚集IO技术(scatter-gather)相关推荐

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

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

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

    文章目录 用户空间IO缓冲区产生 IO缓冲区 描述 IO缓冲区的写模式 自定义IO缓冲区 用户空间IO缓冲区产生 系统调用过程中会产生的开销如下: 切换CPU到内核态 进行数据内容的拷贝,从用户态到内 ...

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

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

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

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

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

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

  6. matlab读int16读文件_MATLAB: 使用内存映射加快文件读写

    内存映射是将磁盘上某文件的一部分或整个文件映射到应用程序地址空间内某个地址范围的一种机制.然后,应用程序可采用与访问动态内存相同的方法访问磁盘上的文件.与使用fread和fwrite等函数相比,能够加 ...

  7. linux匿名内存 pmap,linux显示进程的内存映射pmap

    pmap命令可以显示进程的内存映射,使用这个命令可以找出造成内存瓶颈的原因. # pmap -d PID 显示PID为47394进程的内存信息. # pmap -d 47394 输出样例: 47394 ...

  8. mmap内存映射原理

    mmap概念 mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系.  特点:实现这样的映射关系后,进程就可以 ...

  9. Linux 内存映射之文件映射

    Linux 内存映射之文件映射 文章目录 Linux 内存映射之文件映射 文件映射 匿名映射 文件的私有映射与共享映射 创建映射 mmap() 文件映射的边界情况 正常文件范围的内存映射 超出文件范围 ...

最新文章

  1. AI顶会组团“改版”:NeurIPS DDL推迟3周,ICLR连赞助商都要开视频,CVPR还在死撑...
  2. 4、JVM垃圾回收机制、新生代的GC、GC(Minor GC、FullGC)、GC日志、JVM参数选项、元空间(笔记)
  3. 异常-简单的异常捕获
  4. Docker最全教程之使用Tencent Hub来完成CI(十)
  5. 404. Sum of Left Leaves
  6. c语言 函数的参数传递示例_isunordered()函数与C ++中的示例
  7. android so abi适配,Android NDK学习(六): so文件兼容之abiFilters的使用
  8. java优先级队列使用
  9. 分布式红锁的加锁的lua底层设计原理
  10. 【机房收费系统C#版】——导出Excel
  11. 【gp数据库】查询GP中某张表的分布键信息
  12. 有一根27厘米的细木杆java_百度笔试题 蚂蚁爬杆
  13. DHCP 客户端移动位置后无法获取IP地址的解决办法和原因分析
  14. invalid byte sequence for encoding utf8 0xcb 0xef
  15. 会计平台常见问题QA
  16. express跨域配置
  17. Cadence Allegro Artwork光绘文件参数设置
  18. C#数据结构:两栈实现队列,两队列实现栈
  19. QtSpeech会让Qt说话
  20. 洛谷 P1496 火烧赤壁(离散化

热门文章

  1. Myeclipse安装、配置、测试
  2. 基于libmad库的MP3解码简析
  3. C#条件判断-根据条件判断要走的路-if结构
  4. Hadoop学习笔记一 简要介绍
  5. 《OpenCV3编程入门》学习笔记8 图像轮廓与图像分割修复(六)图像修补
  6. 《OpenCV3编程入门》学习笔记7 图像变换(二 )霍夫变换
  7. 学计算机技术基础B课件,大学计算机基础试题一
  8. hmcl离线登陆_最好用的Java版启动器HMCL
  9. 用matlab自己搭建bp神经网络,怎样在matlab里建立一个BP神经网络模型?
  10. android 刷新某条数据_Android 支持刷新、加载更多、带反弹效果的RecyclerView