分散输入和集中输出(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. Thinkphp学习笔记7-输入变量

    在Web开发过程中,我们经常需要获取系统变量或者用户提交的数据,这些变量数据错综复杂,而且一不小心就容易引起安全隐患,但是如果利用好ThinkPHP提供的变量获取功能,就可以轻松的获取和驾驭变量了. ...

  2. c# String.IndexOf 方法 string查找字符串

    c# String.IndexOf 方法 (value, [startIndex], [count]) 报告指定字符在此实例中的第一个匹配项的索引.搜索从指定字符位置开始,并检查指定数量的字符位置. ...

  3. 无法加载协定为“JavaWebService.UserInfoDelegate”的终结点配置部分,因为找到了该协定的多个终结点配置。请按名称指示首选的终结点配置部分。

    原因是: 在vs 2008中使用C#,多次添加/删除服务引用后,app.config文件并不会自动修改, 在添加/删除后,会生成多个“endpoint”,手工删除即可. app.config中的内容: ...

  4. OPENERP 构建动态视图

    来自:http://shine-it.net/index.php/topic,16142.0.html 在openerp展示界面通常是通过定义class的view(xml文件)来实现的. 有时这种方法 ...

  5. [翻译] C# 8.0 新特性 Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南) 【由浅至深】redis 实现发布订阅的几种方式 .NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐

    [翻译] C# 8.0 新特性 2018-11-13 17:04 by Rwing, 1179 阅读, 24 评论, 收藏, 编辑 原文: Building C# 8.0[译注:原文主标题如此,但内容 ...

  6. 如何用C#做一个悬浮窗口程序

    用C#做一个像FlashGet的悬浮窗口,其实很简单,不像以前需要调用很多系统API.大致的步骤如下. 首先是主窗体部分,即要判断窗体的状态来决定是否显示悬浮窗口. 局部成员声明: private F ...

  7. spi flash偶尔出现写入错误的情况

    spi flash W25Q128会偶尔出现写入错误的情况,会发现读出的值和写入的值不一致,需加入2次读出比较判断. W25QXX_Read(&temp_date_count,0x000000 ...

  8. 给ECharts添加右键点击事件,实现右键功能菜单

    由于项目的需要,使用ECharts 的力导向图来实现 整个EDW数据架构的血缘分析,由于ECharts并没有给组件定义有右键的事件,同时ECharts是开源的项目,所以研究了下源码,将ECharts2 ...

  9. Bootloader和Root

    1. Unlock Bootloader是解除系统启动加载器(Bootloader)的原厂限制, 让用户可以使用到更多的功能(如刷新内核.刷ROM.修改超频....) Bootloader(系统启动加 ...

  10. Python在ubuntu下常用开发包名称

    build-essential python3-setuptools python-setuptools-doc python3-all-dev python3-wheelwheel时pip支持的一种 ...