Linux:何时使用分散/收集IO(readv,writev)与具有fread的大型缓冲区

分散收集 (即writevwritev )中,Linux读入多个缓冲区并从多个缓冲区写入。

如果说,我有一个3缓冲区的vector,我可以使用readv ,或者我可以使用一个单一的缓冲区,这是3个缓冲区的组合大小,做fread

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

writevwritev提供的主要便利是:

  1. 它允许使用不连续的数据块。 即缓冲区不需要是数组的一部分,而是分开分配。
  2. I / O是“primefaces”的。 即如果你写一个writev ,vector中的所有元素都将被写入一个连续的操作,而其他进程完成的写操作不会发生在它们之间。

比如说,你的数据是自然分割的,来自不同的来源:

 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 (overhead)将它们复制到一个内存块中,然后进行单个write调用。 然后写将是primefaces的。
  2. 进行三个独立的调用来write (开销)。 而且,来自其他进程的write调用可以在这些写入之间散布(不是primefaces的)。

如果你使用writev代替,那么writev

  1. 你只需要进行一次系统调用,而不需要三个memcpy来创build一个缓冲区。
  2. 此外,三个缓冲区是primefaces写入,作为一个块写入。 即如果其他进程也写入,则这些写入不会进入三个向量的写入之间。

所以你会做这样的事情:

 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