在 scatter 和 gather (即readv
和writev
)中,Linux读入多个缓冲区并从多个缓冲区写入。
如果说,我有3个缓冲区的向量,我可以使用readv
,或者我可以使用单个缓冲区,其总大小为3个缓冲区并且fread
。
因此,我很困惑:应该使用分散/聚集的哪些情况以及何时应该使用单个大缓冲区?
答案 0 :(得分:91)
readv
,writev
提供的主要便利是:
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
,则必须选择:
memcpy
(开销)将其复制到一个内存块中,然后进行一次write
调用。然后写入将是原子的。write
(开销)进行三次单独调用。此外,来自其他进程的write
调用可以在这些写入之间穿插(非原子)。如果你使用writev
代替它,那就好了:
memcpy
从这三次调用中生成一个缓冲区。所以你会做类似的事情:
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);
来源: