Шрифт:
F_DUPFD | Разместить новый файловый дескриптор, значение которого больше или равно значению третьего аргумента. Новый файловый дескриптор будет указывать на тот же открытый файл, что и fildes . Действие аналогично вызову функции dup(2) или dup2(2): fddup = fcntl(fd, F_DUPFD, fildes2) |
F_GETFD | Возвратить признак сохранения дескриптора при запуске новой программы (выполнении системного вызова exec(2)) — флаг close-on-exec ( FD_CLOEXEC ). Если флаг установлен, то при вызове exec(2) файл, ассоциированный с данным дескриптором, будет закрыт |
F_SETFD | Установить флаг close-on-exec согласно значению, заданному третьим аргументом |
F_GETFL | Возвратить режим доступа к файлу, ассоциированному с данным дескриптором. Флаги, установленные в возвращаемом значении, полностью соответствуют режимам открытия файла, задаваемым функции open(2). Их значения приведены в табл. 2.8. Рассмотрим пример: oflags = fcntl(fd, F_GETFL, 0); /* Выделим биты, определяющие режим доступа */ accbits = oflags & O_ACCMODE; if (accbits == O_RDONLY) printf("Файл открыт только для чтения\n"); else if (accbits == O_WRONLY) printf("Файл открыт только для записи\n"); else if (accbits == O_RDWR) printf("Файл открыт для чтения и записи\n"); |
F_SETFL | Установить режим доступа к файлу согласно значению, переданному в третьем аргументе. Могут быть изменены только флаги O_APPEND , O_NONBLOCK , O_SYNC и O_ASYNC . |
F_GETLK | Проверить существование блокирования записи файла. Блокирование записи, подлежащее проверке, описывается структурой flock , указатель на которую передается в качестве третьего аргумента. Если существующие установки не позволяют выполнить блокирование, определенное структурой flock, последняя будет возвращена с описанием текущего блокирования записи. Данная команда не устанавливает блокирование, а служит для проверки его возможности. Более подробно блокирование записей описано в главе 4, в разделе "Блокирование доступа к файлу". |
F_SETLK | Установить блокирование записи файла. Структура flock описывает блокирование, и указатель на нее передается в качестве третьего аргумента. При невозможности блокирования fcntl(2) возвращается С ошибкой EACCESS или EAGAIN . |
F_SETLKW | Аналогично предыдущему, но при невозможности блокирования по причине уже существующих блокировок, процесс переходит в состояние сна, ожидая, пока последние будут освобождены. Последняя буква W в названии действия означает wait (ждать). |
Стандартная библиотека ввода/вывода
Функции, которые мы только что рассмотрели представляют интерфейс ввода/вывода между приложениями и ядром операционной системы. Хотя их использование напоминает использование библиотечных функций С, по существу они представляют собой лишь "обертки" к функциям ядра UNIX, фактически выполняющим операции ввода/вывода.
Однако программисты редко используют этот интерфейс низкого уровня, предпочитая возможности, предоставляемые стандартной библиотекой ввода/вывода. Функции этой библиотеки обеспечивают буферизованный ввод/вывод и более удобный стиль программирования. Для использования функций этой библиотеки в программу должен быть включен файл заголовков <stdio.h>. Эти функции входят в стандартную библиотеку С (libc.so или libc.a), которая, как правило, подключается по умолчанию на этапе связывания.
Вместо использования файлового дескриптора библиотека определяет указатель на специальную структуру данных (структура
Связь потоков стандартной библиотеки с файловыми дескрипторами приведена в табл. 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(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)) построчно при обнаружении конца строки (символа перевода каретки). Такой тип буферизации обычно используется для ассоциированных с терминальными устройствами потоков, которыми, как правило являются стандартные потоки ввода и вывода.
Отсутствие буферизации. В этом случае библиотека не производит никакой буферизации, фактически являясь только программной оболочкой системных вызовов. При этом достигаются минимальные задержки операций чтения и записи, необходимые, например, при выводе сообщений об ошибках. Отсутствие буферизации характерно для стандартного потока вывода сообщений об ошибках.