scatterおよびgather(つまり、readv
およびwritev
)では、Linuxは複数のバッファーへの読み取りと複数のバッファーからの書き込みを行います。
たとえば、3つのバッファーのベクトルがある場合、readv
を使用できます。OR 3つのバッファーを組み合わせたサイズの単一のバッファーを使用して、fread
。
したがって、私は混乱しています:どのケースでスキャッター/ギャザーを使用する必要があり、いつ単一の大きなバッファーを使用する必要がありますか?
readv
、writev
が提供する主な利便性は次のとおりです。
writev
を実行すると、ベクター内のすべての要素が1つの連続した操作で書き込まれ、他のプロセスで行われた書き込みはそれらの間に発生しません。例えばたとえば、データは自然にセグメント化されており、さまざまなソースからのものです。
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();
現在、3つの「バッファ」はすべてnot1つの大きな連続ブロックです。ただし、何らかの理由で(たとえば、ファイル形式のファイルヘッダー内のフィールドであるなど)、ファイルに連続して書き込みたい場合があります。
write
を使用する場合、次のいずれかを選択する必要があります。
memcpy
(オーバーヘッド)を使用して1つのメモリブロックにコピーし、その後に単一のwrite
呼び出しを続けます。その後、書き込みはアトミックになります。write
(オーバーヘッド)を3回個別に呼び出します。また、他のプロセスからの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);
ソース: