スキャッターアンドギャザー(つまりreadv
、および)ではwritev
、Linuxは複数のバッファーに読み取り、複数のバッファーから書き込みます。
たとえば、3つのバッファーのベクトルがある場合は、を使用できますreadv
。または、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つの「バッファ」はすべて1つの大きな連続ブロックではありません。ただし、何らかの理由でそれらを連続してファイルに書き込みたい場合(たとえば、ファイル形式のファイルヘッダーのフィールドである場合)。
使用するwrite
場合は、次のいずれかを選択する必要があります。
memcpy
(オーバーヘッド)を使用してそれらをメモリの1つのブロックにコピーし、その後に1回のwrite
呼び出しを行います。次に、書き込みはアトミックになります。write
(オーバーヘッド)に3つの別々の呼び出しを行います。また、write
他のプロセスからの呼び出しは、これらの書き込みの間に散在する可能性があります(アトミックではありません)。writev
代わりに使用する場合、そのすべてが良いです:
memcpy
を作成し、3つから1つのバッファを作成する必要はありません。したがって、次のようなことを行います。
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);
出典: