В Linux 2.6.30 также были добавлены два новых системных вызова, сочетающих в себе функциональные возможности фрагментированного ввода-вывода с возможностью выполнения ввода-вывода по указанному смещению: preadv() и pwritev(). Это нестандартные системные вызовы, которые также доступны в современных BSD-системах.
#define _BSD_SOURCE
#include
ssize_t preadv(int
Возвращает количество считанных байтов, 0 при EOF или –1 при ошибке
ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
Возвращает количество записанных байтов или –1 при ошибке
Системные вызовы preadv() и pwritev() выполняют ту же задачу, что и readv() и writev(), но осуществляют ввод/вывод в отношении того места в файле, которое указано смещением (наподобие pread() и pwrite()). Эти системные вызовы не меняют смещение файла.
Эти системные вызовы окажутся полезными для приложений (например, многопоточных), где нужно сочетать преимущества фрагментированного ввода-вывода с возможностью выполнения ввода-вывода в месте, не зависящем от текущего файлового смещения.
Системные вызовы truncate() и ftruncate() устанавливают для файла размер, соответствующий значению, указанному в аргументе length.
#include
int truncate(const char *
int ftruncate(int
Оба возвращают 0 при успешном завершении или –1 при ошибке
Если длина файла больше значения, указанного в аргументе length, избыточные данные утрачиваются. Если текущее значение длины файла меньше значения аргумента length, файл наращивается за счет добавления последовательности нулевых байтов, или дыры.
Эти два системных вызова отличаются друг от друга способом указания файла. При использовании truncate() файл, который должен быть доступен и открыт для записи, указывается в строке путевого имени — pathname. Если pathname является символьной ссылкой, она разыменовывается. Системный вызов ftruncate() получает дескриптор того файла, который был открыт для записи. Файловое смещение для файла не изменяется.
Если значение аргумента length для ftruncate() превышает текущий размер файла, в спецификации SUSv3 разрешается проявлять один из двух вариантов поведения: либо файл расширяется (как в Linux), либо системный вызов возвращает ошибку. XSI-совместимые системы должны принять первую линию поведения. В SUSv3 требуется, чтобы truncate() всегда расширял файл, если значение length превышает его текущий размер.
Уникальность системного вызова truncate() состоит в том, что это единственный системный вызов, способный изменять содержимое файла, не получая для него предварительно дескриптор посредством вызова open() (или какими-то другими способами).
Указание флага O_NONBLOCK при открытии файла служит двум целям.
• Если файл не может быть открыт немедленно, вызов open() вместо блокирования возвращает ошибку. Одним из случаев, при котором open() может проводить блокировку, является использование этого системного вызова в отношении FIFO-устройств (см. раздел 44.7).
• После успешного завершения open() дальнейшие операции ввода-вывода также являются неблокирующими. Если системный вызов ввода-вывода не может завершиться немедленно, то либо выполняется частичное портирование данных, либо системный вызов дает сбой с выдачей одной из ошибок: EAGAIN или EWOULDBLOCK. Какая из ошибок будет возвращена, зависит от системного вызова. В Linux, как и во многих реализациях UNIX, эти две константы ошибок синонимичны.
Неблокирующий режим может использоваться с устройствами (например, с терминалами и псевдотерминалами), конвейерами, FIFO-устройствами и сокетами. (Поскольку при использовании open() дескрипторы для конвейеров и сокетов не получаются, этот флаг должен устанавливаться при использовании операции F_SETFL системного вызова fcntl(), рассматриваемого в разделе 5.3.)
Для обычных файлов указание флага O_NONBLOCK, как правило, не требуется, поскольку буферный кэш ядра гарантирует, что ввод-вывод в отношении обычных файлов, как описывается в разделе 13.1, не блокируется. Но O_NONBLOCK оказывает влияние на обычные файлы, когда используется обязательная блокировка файлов (см. раздел 51.4).
Неблокирующий ввод-вывод будет также рассматриваться в разделе 44.9 и в главе 59.