Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах

Роббинс Арнольд

Шрифт:

4.4. Ввод и вывод

Все операции Linux по вводу/выводу осуществляются посредством дескрипторов файлов. Данный раздел знакомит с дескрипторами файлов, описывает, как их получать и освобождать, и объясняет, как выполнять с их помощью ввод/вывод.

4.4.1. Понятие о дескрипторах файлов

Дескриптор файла является целым значением. Действительные дескрипторы файлов начинаются с 0 и растут до некоторого установленного системой предела. Эти целые фактически являются индексами таблицы открытых файлов для каждого процесса (Таблица поддерживается внутри операционной системы; она недоступна запущенным программам.) В большинстве современных систем размеры таблиц большие. Команда '

ulimit -n
'
печатает это значение:

$ ulimit -n

1024

Из С максимальное число открытых файлов возвращается функцией

getdtablesize
(получить размер таблицы дескрипторов):

#include <unistd.h> /* Обычный */

int getdtablesize(void);

Следующая небольшая программа выводит результат работы этой функции:

/* ch04-maxfds.с --- Демонстрация getdtablesize. */

#include <stdio.h> /* для fprintf, stderr, BUFSIZ */

#include <unistd.h> /* для ssize_t */

int main(int argc, char **argv) {

 printf("max fds: %d\n", getdtablesize);

 exit(0);

}

Неудивительно, что после компиляции и запуска эта программа выводит то же значение, что и

ulimit
:

$ ch04-maxfds

max fds: 1024

Дескрипторы файлов содержатся в обычных переменных

int
; для использования с системными вызовами ввода/вывода можно увидеть типичные объявления вида '
int fd
'. Для дескрипторов файлов нет предопределенного типа.

В обычном случае каждая программа начинает свою работу с тремя уже открытыми для нее дескрипторами файлов. Это стандартный ввод, стандартный вывод и стандартная ошибка, с дескрипторами файлов 0, 1 и 2 соответственно. (Если не было использовано перенаправление, каждый из них связан с клавиатурой и с экраном.)

Очевидные символические константы. Оксюморон?

При работе с системными вызовами на основе дескрипторов файлов и стандартных ввода, вывода и ошибки целые константы 0, 1 и 2 обычно используются прямо в коде. В подавляющем большинстве случаев использование таких символических констант (manifest constants) является плохой мыслью. Вы никогда не знаете, каково значение некоторой случайной целой константы и имеет ли к ней какое-нибудь отношение константа с тем же значением, использованная в другой части кода. С этой целью стандарт POSIX требует объявить следующие именованные константы (symbolic constants) в

<unistd.h>
:

STDIN_FILENO
«Номер файла» для стандартного ввода: 0.

STDOUT_FILENO 
Номер файла для стандартного вывода: 1.

STDERR_FILENO 
Номер файла для стандартной ошибки: 2.

Однако, по нашему скромному мнению, использование этих макросов избыточно. Во-первых, неприятно набирать 12 или 13 символов вместо 1. Во-вторых, использование 0, 1 и 2 так стандартно и так хорошо известно, что на самом деле нет никаких оснований для путаницы в смысле этих конкретных символических констант.

С другой стороны, использование этих констант не оставляет сомнений в намерениях программиста. Сравните это утверждение:

int fd = 0;

Инициализируется ли

fd
значением стандартного ввода, или же программист благоразумно инициализирует свои переменные подходящим значением? Вы не можете этого сказать.

Один из подходов (рекомендованный Джеффом Колье (Geoff Collyer)) заключается в использовании следующего определения

enum
:

enum { Stdin, Stdout, Stderr };

Затем эти константы можно использовать вместо 0, 1 и 2. Их легко читать и печатать.

4.4.2. Открытие и закрытие файлов

Новые дескрипторы

файлов получают (наряду с другими источниками) в результате системного вызова
open
. Этот системный вызов открывает файл для чтения или записи и возвращает новый дескриптор файла для последующих операций с этим файлом. Мы видели объявление раньше:

#include <sys/types.h> /* POSIX */

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

int open(const char *pathname, int flags, mode_t mode);

Три аргумента следующие:

const char *pathname

Строка С, представляющая имя открываемого файла.

int flags

Поразрядное ИЛИ с одной или более констант, определенных в

<fcntl.h>
. Вскоре мы их рассмотрим.

mode_t mode

Режимы доступа для создаваемого файла. Это обсуждается далее в главе, см. раздел 4.6 «Создание файлов». При открытии существующего файла опустите этот параметр [46] .

46

open
является одним из немногих варьирующих (variadic) системных вызовов — Примеч. автора.

Возвращаемое open значение является либо новым дескриптором файла, либо -1, означающим ошибку, в этом случае будет установлена

errno
. Для простого ввода/вывода аргумент
flags
должен быть одним из значений из табл. 4.3.

Таблица 4.3. Значения

flags
для
open

Именованная константа Значение Комментарий
O_RDONLY
0 Открыть файл только для чтения, запись невозможны
O_WRONLY
1 Открыть файл только для записи, чтение невозможно
O_RDWR
2 Открыть файл для чтения и записи

Вскоре мы увидим пример кода. Дополнительные значения

flags
описаны в разделе 4.6 «Создание файлов». Большой объем ранее написанного кода Unix не использовал эти символические значения. Вместо этого использовались числовые значения. Сегодня это рассматривается как плохая практика, но мы представляем эти значения, чтобы вы их распознали, если встретитесь с ними

Системный вызов

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

#include <unistd.h> /* POSIX */

int close(int fd);

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

Если вы будете игнорировать возвращаемое значение, специально приведите его к типу

void
, чтобы указать, что вам не нужен результат:

(void)close(fd); /* отказ от возвращаемого значения */

Легкомысленность этого совета в том, что слишком большое количество приведений к

void
имеют тенденцию загромождать код. Например, несмотря на принцип «всегда проверять возвращаемое значение», чрезвычайно редко можно увидеть код, проверяющий возвращаемое значение
printf
или приводящий его к
void
. Как и со многими аспектами программирования на С, здесь также требуются опыт и рассудительность.

Поделиться:
Популярные книги

Путь одиночки. Книга 2

Понарошку Евгений
2. Одиночка
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Путь одиночки. Книга 2

Студент из прошлого тысячелетия

Еслер Андрей
2. Соприкосновение миров
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Студент из прошлого тысячелетия

Ветер с севера

Щепетнов Евгений Владимирович
5. Нед
Фантастика:
фэнтези
8.83
рейтинг книги
Ветер с севера

Убивать чтобы жить 8

Бор Жорж
8. УЧЖ
Фантастика:
боевая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 8

На границе империй. Том 9. Часть 5

INDIGO
18. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 5

Звездная Кровь. Изгой VII

Елисеев Алексей Станиславович
7. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
технофэнтези
рпг
фантастика: прочее
попаданцы
5.00
рейтинг книги
Звездная Кровь. Изгой VII

Я еще не князь. Книга XIV

Дрейк Сириус
14. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я еще не князь. Книга XIV

Газлайтер. Том 9

Володин Григорий
9. История Телепата
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Газлайтер. Том 9

Отморозок 3

Поповский Андрей Владимирович
3. Отморозок
Фантастика:
попаданцы
5.00
рейтинг книги
Отморозок 3

Кодекс Крови. Книга ХIV

Борзых М.
14. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХIV

Гримуар тёмного лорда I

Грехов Тимофей
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Гримуар тёмного лорда I

#Бояръ-Аниме. Газлайтер. Том 13

Володин Григорий Григорьевич
13. История Телепата
Фантастика:
боевая фантастика
аниме
попаданцы
фэнтези
5.00
рейтинг книги
#Бояръ-Аниме. Газлайтер. Том 13

Черный маг императора 2

Герда Александр
2. Черный маг императора
Фантастика:
юмористическая фантастика
попаданцы
аниме
6.00
рейтинг книги
Черный маг императора 2

Эволюционер из трущоб. Том 9

Панарин Антон
9. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 9