Читать книгу 📗 "Операционная система UNIX - Робачевский Андрей Михайлович"
extern FILE *stdin;extern FILE *stdout;extern FILE *stderr;Связь потоков стандартной библиотеки с файловыми дескрипторами приведена в табл. 2.9.
Таблица 2.9. Стандартные потоки и их дескрипторы
| Файловый дескриптор | Поток (указатель) | Описание |
|---|---|---|
| 0 | stdin | Стандартный ввод |
| 1 | stdout | Стандартный вывод |
| 2 | stderr | Сообщения об ошибках |
Таблица 2.10. Наиболее употребительные функции стандартной библиотеки ввода/вывода
| Функция | Назначение |
|---|---|
| fopen(3S) | Открывает файл с указанным именем и возвращает файловый указатель, ассоциированный с данным файлом |
| fclose(3S) | Закрывает поток, освобождая буферы |
| fflush(3S) | Очищает буфер потока, открытого на запись |
| getc(3S) | Считывает символ из потока |
| putc(3S) | Записывает символ в поток |
| gets(3S) | Считывает строку из потока |
| puts(3S) | Записывает строку в поток |
| fread(3S) | Считывает указанное число байтов из потока (бинарный ввод) |
| fwrite(3S) | Записывает указанное число байтов в поток (бинарный вывод) |
| fseek(3S) | Позиционирует указатель в потоке |
| printf(3S) | Производит форматированный вывод |
| scanf(3S) | Производит форматированный ввод |
| fileno(3S) | Возвращает файловый дескриптор данного потока |
Выбор между функциями интерфейса системных вызовов и стандартной библиотеки зависит от многих факторов, в частности, степени контроля ввода/вывода, переносимости программы, простоты. Взгляните, например, на следующие эквивалентные строки программы:
write (1, "Здравствуй, Мир!n", 16);printf("Здравствуй, Мир!n");В первой строке сообщение выводится с использованием системной функции write(2), во второй — с помощью библиотечной функции printf(3S). Помимо того, что второй вариант кажется более лаконичным, отметим еще ряд особенностей. В первом варианте пришлось сделать предположение о том, что файловый дескриптор стандартного вывода равен 1, что может оказаться несправедливым для некоторых систем. Также пришлось явно указать число символов в строке, т.к. write(2) не делает никаких предположений о формате вывода, трактуя его как последовательность байтов. В отличие от wite(2), printf(3S) распознает строки, представляющие собой последовательность символов, заканчивающихся нулем. Функция printf(3S) также позволяет отформатировать выводимые данные для представления их в требуемом виде.
Но основным достоинством функций библиотеки является буферизация ввода/вывода, позволяющая минимизировать число системных вызовов read(2) и write(2). При открытии файла и создании потока функции библиотеки автоматически размещают необходимые буферы, позволяя приложению не заботиться о них.
Библиотека предоставляет три типа буферизации:
□ Полная буферизация. В этом случае операция чтения или записи завершается после того, как будет заполнен буфер ввода/вывода. Ввод/вывод для дисковых файлов, как правило, полностью буферизуется. Буфер размещается с помощью функции malloc(3C) при первом обращении к потоку для чтения или записи и заполняется системными вызовами read(2) или write(2). Это означает, что последующие вызовы getc(3S), gets(3S), putc(3S), puts(3S) и т.д. не инициируют обращений к системным функциям, а будут производить чтение или запись из буфера библиотеки. Содержимое буфера очищается (т.е. данные сохраняются на диске) автоматически, либо при вызове функции fflush(3S).
□ Построчная буферизация. В этом случае библиотека выполняет фактический ввод/вывод (т.е. производит системные вызовы read(2) или write(2)) построчно при обнаружении конца строки (символа перевода каретки). Такой тип буферизации обычно используется для ассоциированных с терминальными устройствами потоков, которыми, как правило являются стандартные потоки ввода и вывода.
□ Отсутствие буферизации. В этом случае библиотека не производит никакой буферизации, фактически являясь только программной оболочкой системных вызовов. При этом достигаются минимальные задержки операций чтения и записи, необходимые, например, при выводе сообщений об ошибках. Отсутствие буферизации характерно для стандартного потока вывода сообщений об ошибках.
Характер буферизации может быть изменен с помощью функций:
#include <stdio.h>void setbuf(FILE *stream, char *buf);int setvbuf(FILE *stream, char *buf, int type, size_t size);Функция setbuf(3S) позволяет включить или отключить буферизацию для потока
streambufBUFSIZNULLФункция setvbuf(3S) позволяет производить более тонкое управление буферизацией, явно указывая, какой ее тип мы хотим установить. Для этого используется аргумент
type_IOFBF | Полная буферизация |
_IOLBF | Построчная буферизация |
_IONBF | Отсутствие буферизации |
В случае полной или построчной буферизации аргумент
sizebufКаждый поток стандартной библиотеки представлен указателем на структуру
FILE_base_ptr_cnt_file_flagst_blksizestatBUFSIZ