Во многих реализациях библиотек языка C, включая glibc, если stdin и stdout ссылаются на терминал, при каждом считывании ввода из stdin происходит скрытое выполнение fflush(stdout). Это выражается в сбросе всех приглашений к вводу, которые записаны в stdout и не включают в себя завершающий символ новой строки (например, printf("Date: ")). Но такое поведение не указано в SUSv3 или C99 и реализовано не во всех библиотеках языка C. Для обеспечения отображения таких приглашений к вводу портируемые программы должны использовать явно указанные вызовы fflush(stdout).

В стандарте C99 изложены два требования для той ситуации, когда поток открыт как для ввода, так и для вывода. Во-первых, за операциями вывода не могут непосредственно следовать операции ввода без выполняемого между ними вызова fflush() или одной из функций позиционирования файлового указателя (fseek(), fsetpos() или rewind()). Во-вторых, за операцией ввода не может непосредственно следовать операция вывода без выполняемого между ними вызова одной из функций позиционирования файлового указателя, если только операция ввода не столкнулась с окончанием файла.

13.3. Управление буферизацией файлового ввода-вывода, осуществляемой в ядре

Сброс буферной памяти ядра для файлов вывода можно сделать принудительным. Иногда это необходимо, если приложение, прежде чем продолжить работу (например, процесс, журналирущий изменения базы данных), должно гарантировать фактическую запись вывода на диск (или как минимум в аппаратный кэш диска).

Перед тем как рассматривать системные вызовы, используемые для управления буферизацией в ядре, будет нелишним рассмотреть несколько относящихся к этому вопросу определений из SUSv3.

Синхронизированный ввод-вывод с обеспечением целостности данных и файла

В SUSv3 понятие синхронизированного завершения ввода-вывода означает «операцию ввода-вывода, которая либо привела к успешному переносу данных [на диск], либо была диагностирована как неудачная».

В SUSv3 определяются два различных типа завершений синхронизированного ввода-вывода. Различие между типами касается метаданных («данных о данных»), описывающих файл. Ядро хранит их вместе с данными самого файла. Подробности метаданных файла будут рассмотрены в разделе 14.4 при изучении индексных дескрипторов файлов. Пока же будет достаточно отметить, что файловые метаданные включают такую информацию, как сведения о владельце файла и его группе, полномочия доступа к файлу, размер файла, количество жестких ссылок на файл, метки времени, показывающие время последнего обращения к файлу, время его последнего изменения и время последнего изменения метаданных, а также указатели на блоки данных.

Первым типом завершения синхронизированного ввода-вывода в SUSv3 является завершение с целостностью данных. При обновлении данных файла должен быть обеспечен перенос информации, достаточной для того, чтобы позволить в дальнейшем извлечь эти данные для продолжения работы.

• Для операции чтения это означает, что запрошенные данные файла были перенесены (с диска) в процесс. Если есть отложенные операции записи, которые могут повлиять на запрошенные данные, данные будут перенесены на диск до выполнения чтения.

• Для операции записи это означает, что данные, указанные в запросе на запись, были перенесены (на диск), как и все метаданные файла, требуемые для извлечения этих данных. Ключевой момент, на который нужно обратить внимание: чтобы обеспечить извлечение данных из измененного файла, необязательно переносить все медатанные файла. В качестве примера атрибута метаданных измененного файла, который нуждается в переносе, можно привести его размер (если операция записи приводит к увеличению размера файла). В противоположность этому метки времени изменяемого файла не будут нуждаться в переносе на диск до того, как произойдет последующее извлечение данных.

Вторым типом завершения синхронизированного ввода-вывода, определенного в SUSv3, является завершение с целостностью файла. Это расширенный вариант завершения синхронизованного ввода-вывода с целостностью данных. Отличие этого режима заключается в том, что в ходе обновления файла все его метаданные переносятся на диск, даже если этого не требуется для последующего извлечения данных файла.

Системные вызовы для управления буферизацией, проводимой в ядре при файловом вводе-выводе

Системный вызов fsync() приводит к сбросу всех буферизованных данных и всех метаданных, которые связаны с открытым файлом, имеющим дескриптор fd. Вызов fsync() приводит файл в состояние целостности (файла) после завершения синхронного ввода-вывода.

Перейти на страницу:

Похожие книги