在分散和收集(即readv
和writev
)中,Linux读入多个缓冲区,并从多个缓冲区进行写操作。
如果说,我有3个缓冲区的向量,我可以使用readv
,或者我可以使用单个缓冲区,这是3个缓冲区的组合大小,并且可以做到fread
。
因此,我感到困惑:在哪些情况下应使用分散/聚集功能,何时应使用单个大缓冲区?
Answers:
通过提供的主要便利readv
,writev
是:
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();
现在,所有三个“缓冲区”是不是一个大的连续的块。但是无论出于何种原因,您都希望将它们连续写入文件中(例如,它们是文件格式的文件头中的字段)。
如果使用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);
资料来源:
readv()
或期间到达writev()
,则这些系统调用(取决于SA_RESTART)将返回少于请求的字节数。
Linux System Programming
书中,他们说,readv or writev can experience any of the errors of the read() and write() system calls, and will, upon receiving such errors, set the same errno codes.
那么读书会回来EINTR
吗?或在readv的原子读取之间发生的信号将发生什么?它会被忽略还是排队。