Книга: Разработка приложений в среде Linux. Второе издание
13.4.1. Разбросанное/сборное чтение и запись
13.4.1. Разбросанное/сборное чтение и запись
Приложениям часто требуется читать и записывать данные различных типов в последовательные области файла. Несмотря на то что это можно делать сравнительно легко с помощью множества вызовов read()
и write()
, такое решение не является особо эффективным. Вместо этого приложения могут перемещать все данные в последовательную область памяти, делая возможным один системный вызов. Однако эти действия приводят к множеству ненужных операций с памятью.
Linux предлагает системные вызовы readv()
и writev()
, реализующие разбросанное/сборное чтение и запись[98]. В отличие от стандартных элементов своего уровня, получающих по одному указателю и размеру буфера, эти системные вызовы получают массивы записей, каждая запись которых описывает буфер. Буферы читаются или записываются в том порядке, в каком они приведены в массиве. Каждый буфер описывается с помощью структуры struct iovec
.
#include <sys/uio.h>
struct iovec {
void * iov_base; /* адрес буфера */
size_t iov_len; /* длина буфера */
};
Первый элемент, iov_base
, указывает на буферное пространство. Элемент iov_len
— это количество символов в буфере. Эти элементы представляют собой то же, что и второй и третий параметры, передаваемые read()
и write()
.
Ниже показаны прототипы readv()
и writev()
.
#include <sys/uio.h>
int readv(int fd, const struct iovec * vector, size_t count);
int writev(int fd, const struct iovec * vector, size_t count);
Первый аргумент является файловым дескриптором, с которого можно считывать или на который можно записывать. Второй аргумент, vector
, указывает на массив элементов count struct iovec
. Обе функции возвращают общее количество прочитанных или записанных байтов.
Ниже приведена простая программа-пример, использующая writev()
для отображения простого сообщения на стандартном устройстве вывода.
1: /* gather.с */
2:
3: #include <sys/uio.h>
4:
5: int main(void) {
6: struct iovec buffers[3];
7:
8: buffers[0].iov_base = "hello";
9: buffers[0].iov_len = 5;
10:
11: buffers[1].iov_base = " ";
12: buffers[1].iov_len = 1;
13:
14: buffers[2].iov_base = "worldn";
15: buffers[2].iov_len = 6;
16:
17: writev(1, buffers, 3);
18:
19: return 0;
20: }