在分散和收集(即readvwritev)中,Linux读取了多个缓冲区,并从多个缓冲区中写入数据。

如果说,我有3个缓冲区的 vector ,则可以使用readv,也可以使用单个缓冲区,该缓冲区的总大小为3个缓冲区,并执行fread

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

最佳答案

readvwritev提供的主要便利是:

  • 它允许处理非连续的数据块。即缓冲区不必是数组的一部分,而可以单独分配。
  • I/O是“原子的”。即,如果您执行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,则必须在以下选项之间进行选择:
  • 使用memcpy(开销)将它们复制到一个内存块中,然后调用一个write。然后,写入将是原子的。
  • 分别对write(开销)进行三个调用。同样,来自其他进程的write调用可以散布在这些写入之间(不是原子的)。

  • 如果您改用writev,那么一切都很好:
  • 您只需进行一个系统调用,而无需memcpy即可从这三个系统中创建单个缓冲区。
  • 同样,三个缓冲区以原子方式写入,作为一个块写入。即,如果其他进程也进行写操作,则这些写操作将不会出现在三个 vector 的写操作之间。

  • 因此,您将执行以下操作:
    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);
    

    资料来源:
  • http://pubs.opengroup.org/onlinepubs/009604499/functions/writev.html
  • http://linux.die.net/man/2/readv
  • 10-04 14:40