IT-Swarm.Net

Linux:何时使用分散/聚集 IO (readv,writev)vs一个带fread的大缓冲区

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

如果说,我有一个3个缓冲区的向量,我可以使用readv,OR我可以使用单个缓冲区,其总大小为3个缓冲区并执行fread。.

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

55
Jimm

readvwritev提供的主要便利是:

  1. 它允许使用不连续的数据块。即缓冲区需要 not 是数组的一部分,但是单独分配。.
  2. I/O是'原子'。即,如果执行writev,则向量中的所有元素将在一个连续的操作中写入,而其他进程完成的写入不会在它们之间进行。.

例如比如,您的数据自然是分段的,来自不同的来源:

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();

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

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

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

如果你改用writev,那就好了:

  1. 您只进行一次系统调用,而没有memcpy从这三次调用中生成一个缓冲区。.
  2. 此外,三个缓冲区以原子方式写入,作为一个块写入。即如果其他进程也写入,那么这些写入将不会进入三个向量的写入之间。.

所以你会做类似的事情:

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
91
ArjunShankar

快速,可靠且价格合理的云托管

注册并在30天内获得$50奖金!