Linux:何时使用分散/收集IO(readv,writev)与具有fread的大型缓冲区
在分散和收集 (即writev
和writev
)中,Linux读入多个缓冲区并从多个缓冲区写入。
如果说,我有一个3缓冲区的vector,我可以使用readv
,或者我可以使用一个单一的缓冲区,这是3个缓冲区的组合大小,做fread
。
因此,我很困惑:对于哪些情况应该使用分散/聚集,何时应该使用一个大的缓冲区?
writev
, writev
提供的主要便利是:
- 它允许使用不连续的数据块。 即缓冲区不需要是数组的一部分,而是分开分配。
- 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:
- 使用
memcpy
(overhead)将它们复制到一个内存块中,然后进行单个write
调用。 然后写将是primefaces的。 - 进行三个独立的调用来
write
(开销)。 而且,来自其他进程的write
调用可以在这些写入之间散布(不是primefaces的)。
如果你使用writev
代替,那么writev
:
- 你只需要进行一次系统调用,而不需要三个
memcpy
来创build一个缓冲区。 - 此外,三个缓冲区是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);
资料来源: