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

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

Жанры

Linux программирование в примерах
Шрифт:

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

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

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

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

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

int close(int fd);

В

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

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

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

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

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

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

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

Система закрывает все открытые файлы, когда процесс завершается, но — за исключением 0, 1 и 2 — плохая манера полагаться на это.

Когда

open
возвращает новый дескриптор файла, она всегда возвращает наименьшее неиспользуемое целое значение. Всегда. Поэтому, если открыты дескрипторы файлов 0–6 и программа закрывает дескриптор файла 5, следующий вызов
open
вернет 5, а не 7. Это поведение важно; далее в книге мы увидим, как оно используется для аккуратной реализации многих важных особенностей Unix, таких, как перенаправление ввода/вывода и конвейеризация (piping)

4.4.2.1. Отображение переменных

FILE*
на дескрипторы файлов

Стандартные библиотечные функции ввода/вывода и переменные

FILE*
из
<stdio.h>
, такие, как
stdin
,
stdout
и
stderr
, построены поверх основанных на дескрипторах файлов системных вызовах.

Иногда полезно получить непосредственный доступ к дескриптору файла, связанному с указателем файла

<stdio.h>
, если вам нужно сделать что-либо, не определенное стандартом С ISO. Функция
fileno
возвращает лежащий в основе дескриптор файла:

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

int fileno(FILE *stream);

Пример

мы увидим позже, в разделе 4.4.4. «Пример: Unix cat».

4.4.2.2. Закрытие всех открытых файлов

Открытые файлы наследуются порожденными процессами от своих родительских процессов. Фактически они являются общими. В частности, общим является положение в файле. Подробности мы оставим для дальнейшего обсуждения в разделе 9.1.1.2 «Разделение дескрипторов файлов».

Поскольку программы могут наследовать другие файлы, иногда вы можете увидеть программы, которые закрывают все свои файлы, чтобы начать с «чистого состояния» В частности, типичен код наподобие этого:

int i;

/* оставить лишь 0, 1, и 2 */

for (i = 3; i < getdtablesize; i++)

 (void)close(i);

Предположим, что результат

getdtablesize
равен 1024. Этот код работает, но он делает (1024-3)*2 = 2042 системных вызова.
1020
из них не нужны, поскольку возвращаемое значение
getdtablesize
не изменяется. Вот лучший вариант этого кода:

int i, fds;

for (i = 3, fds = getdtablesize; i < fds; i++)

 (void)close(i);

Такая оптимизация не ухудшает читаемость кода, но может быть заметна разница, особенно на медленных системах. В общем, стоит поискать случаи, когда в циклах повторно вычисляется один и тот же результат, чтобы посмотреть, нельзя ли вынести вычисление за пределы цикла. Хотя в таких случаях нужно убедиться, что вы (а) сохраняете правильность кода и (б) сохраняете его читаемость!

4.4.3. Чтение и запись

Ввод/вывод осуществляется системными вызовами

read
и
write
соответственно:

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

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

ssize_t write(int fd, const void *buf, size_t count);

Каждая функция сделана как можно проще. Аргументами являются дескриптор открытого файла, указатель на буфер для чтения или записи данных и число читаемых или записываемых байтов.

Возвращаемое значение является числом действительно прочитанных или записанных байтов. (Это число может быть меньше запрошенного: при операции чтения это происходит, когда в файле осталось меньше

count
байтов, а при операции записи это случается, когда диск заполнен или произошла еще какая-нибудь ошибка.) Возвращаемое значение -1 означает возникшую ошибку, в этом случае errno указывает эту ошибку. Когда
read
возвращает 0, это означает, что достигнут конец файла.

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

Маленькая женщина Большого

Зайцева Мария
5. Наша
Любовные романы:
эро литература
современные любовные романы
5.00
рейтинг книги
Маленькая женщина Большого

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

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

Двойник Короля 4

Скабер Артемий
4. Двойник Короля
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Двойник Короля 4

Кодекс Охотника. Книга VIII

Винокуров Юрий
8. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга VIII

Вперед в прошлое 5

Ратманов Денис
5. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 5

Уникум

Поселягин Владимир Геннадьевич
1. Уникум
Фантастика:
альтернативная история
4.60
рейтинг книги
Уникум

Принятие

Хайд Адель
3. История Ирэн
Фантастика:
попаданцы
альтернативная история
фэнтези
6.00
рейтинг книги
Принятие

Бастард Императора. Том 2

Орлов Андрей Юрьевич
2. Бастард Императора
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Бастард Императора. Том 2

Агенты ВКС

Вайс Александр
3. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Агенты ВКС

Я не бог. Книга XXXIV

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

Мы – Гордые часть 8

Машуков Тимур
8. Стальные яйца
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Мы – Гордые часть 8

Тринадцатый

NikL
1. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
6.80
рейтинг книги
Тринадцатый

Адвокат

Константинов Андрей Дмитриевич
1. Бандитский Петербург
Детективы:
боевики
8.00
рейтинг книги
Адвокат

Наследие Маозари 6

Панежин Евгений
6. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
фэнтези
эпическая фантастика
5.00
рейтинг книги
Наследие Маозари 6