scattergather(即readvwritev)中,Linux读入多个缓冲区,并从多个缓冲区写入.

如果说,我有一个3个缓冲区的向量,我可以使用readv,或者我可以使用一个缓冲区,它的大小是3个缓冲区和do fread的总和.

因此,我感到困惑:在哪些情况下应该使用分散/聚集,何时应该使用单个大缓冲区?

推荐答案

readvwritev提供的主要便利是:

  1. 它允许处理非连续的数据块.i、 e.缓冲区需要是数组的一部分,但需要单独分配.
  2. I/O是"原子的".i、 e.如果执行writev,向量中的所有元素都将在一个连续操作中写入,而其他进程所做的写入操作将不会发生在它们之间.

e、 g.比如说,你的数据是自然分割的,并且来自不同的来源:

struct foo *my_foo;
struct bar *my_bar;
struct baz *my_baz;

my_foo = get_my_foo();
my_bar = get_my_bar();
my_baz = get_my_baz();

现在,所有三个"缓冲区"都是一个大的连续块.但无论出于何种原因,您都希望将它们连续写入文件(例如,它们是文件格式的文件头中的字段).

如果使用write,则必须在以下选项中进行 Select :

  1. 例如,使用memcpy(开销)将它们复制到一个内存块中,然后进行一次write调用.然后写入将是原子的.
  2. 分别拨打三通write(开销).此外,来自其他进程的write个调用可以在这些写入之间穿插(不是原子的).

如果你用writev来代替,这一切都很好:

  1. 你只需要进行一次系统调用,而不需要从这三次调用中提取一个缓冲区.
  2. 此外,三个缓冲区以原子方式写入,即一个块写入.i、 e.如果其他进程也写入,那么这些写入将不会出现在三个向量的写入之间.

所以你可以这样做:

struct iovec iov[3];

iov[0].iov_base = my_foo;
iov[0].iov_len = sizeof (struct foo);
iov[1].iov_base = my_bar;
iov[1].iov_len = sizeof (struct bar);
iov[2].iov_base = my_baz;
iov[2].iov_len = sizeof (struct baz);

bytes_written = writev (fd, iov, 3);

资料来源:

  1. http://pubs.opengroup.org/onlinepubs/009604499/functions/writev.html
  2. http://linux.die.net/man/2/readv

Linux相关问答推荐

抛出主,即未捕获到SIGSEGV中的异常结果

awk:try 将时间戳字符串转换为unix纪元时间

使用Bash从文件名中删除日期名称

如何将数据从Linux内核中的块驱动程序持久存储到存储中?

条件句if的正确写法是怎样的?

在 bash 中使用 tee 时如何返回错误代码

Linux TTY 操作顺序

awk 打印除最后一列以外的所有内容 + 最后一列

使用 grep 时如何跳过第一行和最后一行?

使用 sed linux 命令和 i sed 命令进行 preprend 时的反向引用

如何使用 shell 脚本将文本文件转换为 JSON 文件

我应该如何从非 root Debian Linux 守护进程登录?

如何安装脚本以从命令行的任何位置运行?

Linux命令行如何接受没有pin的蓝牙设备配对

C hello world 的汇编输出的每一行是什么意思?

带有 curl 的 Linux 脚本来判断 Web 服务是否已启动

如何在字符串中查找子字符串(或如何 grep 变量)?

仅使用 proc 获取本地网络接口地址?

如何让我的 Golang Web 服务器在后台运行?

Linux 上的 NuGet:获取响应流时出错