Операционная система UNIX - страница 60
Библиотека предоставляет три типа буферизации:
□ Полная буферизация. В этом случае операция чтения или записи завершается после того, как будет заполнен буфер ввода/вывода. Ввод/вывод для дисковых файлов, как правило, полностью буферизуется. Буфер размещается с помощью функции malloc(3C) при первом обращении к потоку для чтения или записи и заполняется системными вызовами read(2) или write(2). Это означает, что последующие вызовы getc(3S), gets(3S), putc(3S), puts(3S) и т.д. не инициируют обращений к системным функциям, а будут производить чтение или запись из буфера библиотеки. Содержимое буфера очищается (т.е. данные сохраняются на диске) автоматически, либо при вызове функции fflush(3S).
□ Построчная буферизация. В этом случае библиотека выполняет фактический ввод/вывод (т.е. производит системные вызовы read(2) или write(2)) построчно при обнаружении конца строки (символа перевода каретки). Такой тип буферизации обычно используется для ассоциированных с терминальными устройствами потоков, которыми, как правило являются стандартные потоки ввода и вывода.
□ Отсутствие буферизации. В этом случае библиотека не производит никакой буферизации, фактически являясь только программной оболочкой системных вызовов. При этом достигаются минимальные задержки операций чтения и записи, необходимые, например, при выводе сообщений об ошибках. Отсутствие буферизации характерно для стандартного потока вывода сообщений об ошибках.
Характер буферизации может быть изменен с помощью функций:
>#include
>void setbuf(FILE *stream, char *buf);
>int setvbuf(FILE *stream, char *buf, int type, size_t size);
Функция setbuf(3S) позволяет включить или отключить буферизацию для потока >stream
. В первом случае >buf
должен указывать на буфер размером >BUFSIZ
, во втором его значение должно быть равно >NULL
.
Функция setvbuf(3S) позволяет производить более тонкое управление буферизацией, явно указывая, какой ее тип мы хотим установить. Для этого используется аргумент >type
, который может принимать следующие значения:
>_IOFBF | Полная буферизация |
>_IOLBF | Построчная буферизация |
>_IONBF | Отсутствие буферизации |
В случае полной или построчной буферизации аргумент >size
определяет размер буфера, адресованного указателем >buf
.
Каждый поток стандартной библиотеки представлен указателем на структуру >FILE
, показанную на рис. 2.9, в которой хранится указатель на буфер >_base
, указатель на следующий символ, подлежащий чтению или записи >_ptr
, число байт в буфере >_cnt
, указатель на файловый дескриптор >_file
, с которым ассоциирован данный поток, а также флаги состояния потока >_flag
. При создании буфера библиотека выбирает оптимальный размер для данного потока. Обычно этот размер равен значению поля >st_blksize
структуры >stat
, возвращаемой системным вызовом stat(2), рассмотренный в разделе "Метаданные файла" этой главы. Если определить оптимальный размер невозможно, например для каналов или специальных файлов устройств, выбирается стандартное значение >BUFSIZ
, определенное в файле
Рис. 2.9. Структуры данных потока
Связи
В метаданных каждого файла файловой системы UNIX хранится число связей, определяющее количество имен, которое имеет данный файл. Например, файлы /etc/init.d/lp (или /etc/lp), /etc/rc0.d/K201p, /etc/rc2.d/K201p и /etc/rc2.d/S801p имеют различные имена, но ссылаются на один и тот же физический файл (точнее, метаданные файла) и тем самым обеспечивают доступ к одним и тем же данным. В данном случае число связей файла равно 4. Каждый раз, когда одно из имен файла удаляется, число связей соответственно уменьшается. Когда оно достигнет нуля — данные файла будут удалены. Такой тип связи называется жесткой.
Жесткая связь создается с помощью системного вызова link(2):
>#include
>int link(const char *existing, const char *new);
При этом будет образована новая запись каталога с именем >new
и номером inode указывающим на метаданные файла >existing
. Также будет увеличено число связей. Этим системным вызовом, в частности, пользуется команда ln(1), рассмотренная в главе 1.
Для удаления жесткой связи используется системный вызов