Ответ 1
Основное удобство, предлагаемое readv
, writev
:
- Он позволяет работать с несмежными блоками данных. то есть буферы не должны быть частью массива, но отдельно распределены.
- I/O является "атомарным". т.е. если вы выполняете
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
вызовы из других процессов могут пересекаться между этими write (not atomic).
Если вы используете 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);
Источники: