Есть несколько механизмов, которые может использовать приложение, чтобы дождаться записи данных на физический носитель. Флаг O_SYNC
, описанный ранее в этой главе, при каждой операции записи в файл вызывает блокирование вызывающего процесса до тех пор, пока носитель не будет действительно обновлен. Хотя это, конечно, работает, все же такой подход не является достаточно аккуратным. Обычно приложения не нуждаются в том, чтобы все операции были синхронизированы, гораздо чаще они нуждаются в том, чтобы гарантировать, что некий набор операций завершился перед тем, как может быть начат другой набор операций. Системные вызовы fsync()
и fdatasync()
обеспечивают такую семантику.
#include
int fsync(int fd);
int fdatasync(int fd);
Оба системных вызова приостанавливают приложение до тех пор, пока в файл fd
не будут записаны все данные, fsync()
также ожидает обновления информации в inode файла, подобной времени доступа (информация inode для файлов перечислена в табл. 11.3). Однако ни один из этих вызовов не гарантирует записи на неразрушимое устройство хранения. Современные дисковые приводы имеют большие собственные кэши, поэтому сбой питания может привести к тому, что некоторые данные, сохраненные в кэше, будут потеряны.
11.2.8. Прочие операции
Файловая модель Linux достаточно хорошо поддерживает стандартизацию большинства файловых операций через обобщенные функции наподобие read()
и write()
(например, запись в программный канал выполняется так же, как запись в файл на диске). Однако некоторые устройства поддерживают операции, которые плохо моделируются такой абстракцией. Например, терминальные устройства, представленные как устройства символьные, нуждаются в представлении метода изменения скорости терминала, и приводы CD-ROM, представленные как блочные устройства, нуждаются в том, чтобы знать, кода они должны воспроизводить аудиодорожки, чтобы помочь увеличить производительность работы программистов.
Все эти разнообразные операции доступны через единственный системный вызов — ioctl()
(сокращение для "I/O control" — управление вводом-выводом), прототип которого показан ниже.
#include
int ioctl(int fd, int request, ...);
Хотя часто он применяется следующим образом:
int ioctl (int fd, int request, void *arg);
Всякий раз когда используется ioctl()
, его первый аргумент — это файл, с которым выполняются манипуляции, а второй аргумент указывает операцию, которая должна быть выполнена. Последний аргумент обычно представляет собой указатель на нечто, но на что именно, а так же точная семантика возвращаемого кода зависит от типа файла fd
и типа запрошенной операции. Для некоторых операций arg
— длинное целое вместо указателя; в этих случаях обычно применяется приведение типов. В нашей книге есть множество примеров применения ioctl()
, и вам нет нужды заботиться об ioctl()
до тех пор, пока вы не доберетесь до них.
11.3. Запрос и изменение информации inode
11.3.1. Поиск информации inode
В начале этой главы информационный узел файла (inode) был представлен как структура данных, которая отслеживает информацию о файле, независимо от представления ее для процесса. Например, размер файла является константой в любой момент времени — он не изменяется для разных процессов, которые имеют доступ к этому файлу (сравните это с текущей позицией в файле, которая уникальна для каждого вызова open()
, а не свойство самого файла). Linux предлагает три способа чтения информации inode.
#include
int stat(const char *pathname, struct stat *statbuf);
int lstat (const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
Первая версия, stat()
возвращает информацию inode
для файла, на который осуществляется ссылка через pathname
, следуя всем символическим ссылкам, которые она представляет. Если вы не хотите следовать символическим ссылкам (например, чтобы проверить, не является ли само имя такой ссылкой), то используйте вместо этого lstat()
. Последняя версия, fstat()
, возвращает inode
, на который ссылается текущий открытый файловый дескриптор. Все три системных вызова заполняют структуру struct stat
, на которую указывает параметр statbuf
, информацией о файловом inode. В табл. 11.3 описана информация, доступная в struct stat
.
Таблица 11.3. Члены структуры struct stat