Операционная система 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.

Для удаления жесткой связи используется системный вызов