分散输入和集中输出(Scatter-Gather IO):readvwritev

请问这个v又代表什么?

readv和writev系统调用分别实现了分散输入和集中输出的功能。

#include<sys/uio.h>

ssize_t readv(int fd, const struct iovec *iov, int invcnt);

ssize_t writev(int fd, const struct iovec *iov, int iovcnt);

这些系统调用并非只对单个缓冲区进行读写操作,而是一次即可传输多个缓冲区的数据。数组iov定义了一组用来传输数据的缓冲区。整型数iovcnt指定了iov的成员个数。iov中的每个成员都是如下形式的数据结构。

struct iovec {

void *iov_base;    /* Start address of buffer */

size_t iov_len;       /* Number of bytes to transfer to/from buffer */

};

SUSv3标准允许系统实现对iov中的成员个数加以限制。系统实现可以通过定义<limits.h>文件中的IOV_MAX来通告这一限额,程序也可以在系统运行时调用sysconf(_SC_IOV_MAX)来获取这一限额。SUSv3要求该限额不得少于16。Linux将IOV_MAX的值定义为1024,这是与内核对该向量大小的限制(由内核常量UIO_MAXIOV定义)相对应的。

然而,glibc对readv和writev的封装函数还悄悄做了些额外的工作。若系统调用因iovcnt参数值过大而失败,外壳函数将临时分配一块缓冲区,其大小足以容纳iov参数所有成员所描述的数据缓冲区,随后再执行read或write调用。

分散输入

readv系统调用实现了分散输入的功能:从文件描述符fd所指代的文件中读取一片连续的字节,然后将其散置(分散放置)于iov指定的缓冲区中。这一散置动作从iov[0]开始,依次填满每个缓冲区。

原子性是readv的重要属性。换言之,从调用进程的角度来看,当调用readv时,内核在fd所指代的文件和用户内存之间一次性完成了数据转移。这意味着,假设即使有另一进程(线程)与其共享同一文件偏移量,且在调用readv的同时企图修改文件的偏移量,readv所读区的数据仍将是连续的。

调用readv成功将返回读区的字节数,若文件结束将返回0。调用者必须对返回值进行检查,以验证读取的字节数是否满足要求。若数据不足以填充所有缓冲区,则是会占用部分的缓冲区,其中最后一个缓冲区可能只有部分数据。

分散输出的用途在哪儿呢?

集中输出

writev系统调用实现了集中输出:将iov所指定的所有缓冲区中的数据拼接(集中)起来,然后以连续的字节序列写入文件描述符fd指代的文件中。对缓冲区中数据的集中始于iov[0]所指定的缓冲区,并按数组顺序展开。

像readv调用一样,writev调用也属于原子操作,即所有的数据将一次性的从用户内存传输到fd指代的文件中。因此,在向普通文件写入数据时,writev调用会把所有的请求数据连续写入到文件中,而不会在其他进程(或线程)写操作的影响下分散地写入文件。

如同write调用,writev调用也存在部分写的问题。因此,必须检查writev调用的返回值,以确定写入的字节数是否与要求相符。

readv调用和writev调用的主要优势在于便捷。如下两种方案,任选其一都可替代对writev的调用。

编码时,首先分配一个大缓冲区,随即在从进程地址空间的其他位置将数据复制过来,最后调用write输出其中所有的数据。

发起一列write调用,逐一输出每个缓冲区中的数据。

尽管方案一在语义上等同于writev调用,但仍需在用户空间内分配缓冲区,进行数据复制,很不方便(小女也低)。

方案二在语义上就不同于单次的writev调用,因为发起多次write调用无法保证原子性。更何况,执行一次writev调用要比执行多次write调用开销要小。

在指定的文件偏移量处执行分散输入/集中输出

Linux 2.6.30版本新增了两个系统调用preadv、pwritev,将分散输入/集中供暖输出和指定文件偏移量处的IO二者集于一身。它们并非标准的系统调用,但获得了现代BSD的支持。

Unix系统编程():分散输入和集中输出(Scatter-Gather IO):readv和writev的更多相关文章

  1. 《Linux/Unix系统编程手册》读书笔记2

    <Linux/Unix系统编程手册>读书笔记 目录 第5章: 主要介绍了文件I/O更深入的一些内容. 原子操作,将一个系统调用所要完成的所有动作作为一个不可中断的操作,一次性执行:这样可以 ...

  2. 《Linux/Unix系统编程手册》读书笔记5

    <Linux/Unix系统编程手册>读书笔记 目录 第8章 本章讲了用户和组,还有记录用户的密码文件/etc/passwd,shadow密码文件/etc/shadow还有组文件/etc/g ...

  3. 《Linux/UNIX系统编程手册》第63章 IO多路复用、信号驱动IO以及epoll

    关键词:fasync_helper.kill_async.sigsuspend.sigaction.fcntl.F_SETOWN_EX.F_SETSIG.select().poll().poll_wa ...

  4. 学习《Unix/Linux编程实践教程》(1):Unix 系统编程概述

    0.目录 1.概念 2.系统资源 3.学习方法 4.从用户的角度来理解 Unix 4.1 登录--运行程序--注销 4.2 目录操作 4.3 文件操作 5.从系统的角度来理解 Unix 5.1 网络桥 ...

  5. 《Linux/Unix系统编程手册》读书笔记8 (文件I/O缓冲)

    <Linux/Unix系统编程手册>读书笔记 目录 第13章 这章主要将了关于文件I/O的缓冲. 系统I/O调用(即内核)和C语言标准库I/O函数(即stdio函数)在对磁盘进行操作的时候 ...

  6. 《Linux/Unix系统编程手册》读书笔记6

    <Linux/Unix系统编程手册>读书笔记 目录 第9章 这章主要讲了一堆关于进程的ID.实际用户(组)ID.有效用户(组)ID.保存设置用户(组)ID.文件系统用户(组)ID.和辅助组 ...

  7. 《Linux/Unix系统编程手册》读书笔记3

    <Linux/Unix系统编程手册>读书笔记 目录 第6章 这章讲进程.虚拟内存和环境变量等. 进程是一个可执行程序的实例.一个程序可以创建很多进程. 进程是由内核定义的抽象实体,内核为此 ...

  8. 《Linux/Unix系统编程手册》读书笔记1

    <Linux/Unix系统编程手册>读书笔记 目录 最近这一个月在看<Linux/Unix系统编程手册>,在学习关于Linux的系统编程.之前学习Linux的时候就打算写关于L ...

  9. 《Linux/Unix系统编程手册》读书笔记 目录

    <Linux/Unix系统编程手册>读书笔记1  (创建于4月3日,最后更新4月7日) <Linux/Unix系统编程手册>读书笔记2  (创建于4月9日,最后更新4月10日) ...

随机推荐

  1. MapReduce开发技巧

    数据类型的选择 自定义数据类型 参考:Hadoop提交作业自定义排序和分组 MapWritable/SortedMapWritable Hadoop中可传输的Map集合,和Java中的Map用法差不多 ...

  2. Java中this与super

    l  对象的this引用 作用: this关键字就是让类中一个方法,访问该类中的另一个方法或属性. 1.构造器中引用该构造器正在初始化的对象. 2.在方法中引用调用该方法的对象(哪个对象调用的方法,t ...

  3. JVisualVM简介与内存泄漏实战分析

    JVisualVM简介与内存泄漏实战分析 学习了:https://blog.csdn.net/kl28978113/article/details/53817827

  4. 转:mac下安装homebrew

    见: http://brew.sh 在命令行打开:

  5. [笔记][Java7并发编程实战手冊]3.8 并发任务间的数据交换Exchanger

    [笔记][Java7并发编程实战手冊]系列文件夹 简单介绍 Exchanger 是一个同步辅助类.用于两个并发线程之间在一个同步点进行数据交换. 同意两个线程在某一个点进行数据交换. 本章exchan ...

  6. 基于Struts2、Spring、Hibernate实现的包括多条件查询分页的基础Dao层帮助jar包实现

    操作数据库经常使用操作就是增删查改.每做一次就写一次这些操作太麻烦,也不是必需,特别是写多条件查询并分页时.太痛苦了,所以抽出时间写了个dao帮助jar.导入即搞定!妈妈再有不用操心我的项目了! 转载 ...

  7. java对象的强引用,软引用,弱引用和虚引用

    1.强引用 以前我们使用的大部分引用实际上都是强引用,这是使用最普遍的引用.如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它.当内存空 间不足,Java虚拟机宁愿抛出Out ...

  8. TabHost随着输入法软键盘出现而上浮的问题

    解决办法: 在androidMenifest.xml中的TabHost对应的activity中添加如下代码: android:screenOrientation="portrait" ...

  9. [转载]手工安全测试方法&修改建议

    转载自: Web安全测试(一)-手工安全测试方法&修改建议 1.XSS(Cross-Site Script)跨站脚本攻击 XSS(Cross-Site Script):跨站脚本攻击. 它指的是 ...

  10. MySQL截取字符串函数方法

    函数: 1.从左开始截取字符串 left(str, length) 说明:left(被截取字段,截取长度) 例:select left(content,200) as abstract from my ...