博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Unix系统编程():分散输入和集中输出(Scatter-Gather IO):readv和writev
阅读量:4677 次
发布时间:2019-06-09

本文共 1867 字,大约阅读时间需要 6 分钟。

分散输入和集中输出(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的支持。

转载于:https://www.cnblogs.com/tuhooo/p/8657324.html

你可能感兴趣的文章
github新项目挂历模式
查看>>
编写jquery插件
查看>>
敏捷开发笔记
查看>>
神秘海域:顶级工作室“顽皮狗”成长史(下)
查看>>
C++指针、引用知多少?
查看>>
services 系统服务的启动、停止、卸载
查看>>
css实现背景图片模糊
查看>>
多线程如何确定线程数
查看>>
UGUI RectTransform
查看>>
学前班
查看>>
手把手教您扩展虚拟内存
查看>>
android-samples-mvp
查看>>
oracle 11g r2安装
查看>>
关于自关联1
查看>>
存储控制器、MMU、flash控制器介绍
查看>>
hdu-1814(2-sat)
查看>>
自我反省
查看>>
反射,得到Type引用的三种方式
查看>>
pl sql练习(2)
查看>>
Problem B: 判断回文字符串
查看>>