Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
Как упоминалось, число открытых файлов, если оно большое, ограничивается, и вам всегда следует закрывать файлы, когда работа с ними закончена. Если вы этого не сделаете, то в конечном счете выйдете за пределы лимита дескрипторов файлов, создав ситуацию, которая ведет к потере устойчивости части вашей программы.
Система закрывает все открытые файлы, когда процесс завершается, но — за исключением 0, 1 и 2 — плохая манера полагаться на это.
Когда
open()open()4.4.2.1. Отображение переменных
FILE*Стандартные библиотечные функции ввода/вывода и переменные
FILE*<stdio.h>stdinstdoutstderrИногда полезно получить непосредственный доступ к дескриптору файла, связанному с указателем файла
<stdio.h>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()1020getdtablesize()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);Каждая функция сделана как можно проще. Аргументами являются дескриптор открытого файла, указатель на буфер для чтения или записи данных и число читаемых или записываемых байтов.
Возвращаемое значение является числом действительно прочитанных или записанных байтов. (Это число может быть меньше запрошенного: при операции чтения это происходит, когда в файле осталось меньше
countread()Теперь мы можем показать оставшуюся часть кода для
ch04-catprocess()-36 /*37 * process --- сделать что-то с файлом, в данном случае,38 * послать его в stdout (fd 1).39 * Возвращает 0, если все нормально; в противном случае 1.40 */4142 int43 process(char *file)44 {45 int fd;46 ssize_t rcount, wcount;47 char buffer[BUFSIZ];48 int errors = 0;4950 if (strcmp(file, "-") == 0)51 fd = 0;52 else if ((fd = open(file, O_RDONLY)) < 0) {53 fprintf(stderr, "%s: %s: cannot open for reading: %sn",54 myname, file, strerror(errno));55 return 1;56 }Буфер
bufferBUFSIZ<stdio.h>BUFSIZОсновой процедуры является следующий цикл, который повторно читает данные до тех пор, пока не будет достигнут конец файла или не возникнет ошибка.