ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 11.04.2025
Просмотров: 70
Скачиваний: 0
СОДЕРЖАНИЕ
2.Стандартная библиотека ввода/вывода
1.2. Системные вызовы и их особенности при работе с файлами.
1.2.1. Открытие файла. Системный вызов open().
1.2.2. Закрытие файла. Системный вызов close().
1.2.3. Чтение и запись из/в файл(а). Системные вызовы read() и write().
1.2.4. Создание файла. Системный вызов creat().
1.2.5. Создание жесткой ссылки. Системный вызов link().
1.2.6. Удаление жесткой ссылки. Системный вызов unlink().
1.2.7. Установка указателя в файле. Системный вызов lseek().
1.2.8. Дублирование существующего файлового дескриптора. Системный вызов dup().
1.2.9. Создание однонаправленного канала. Системный вызов pipe().
1.3. Стандартная библиотека ввода/вывода (stdio.H).
1.3.1. Особенности работы с stdio.H.
1.3.3. Обзор функций библиотеки.
1.3.3.1. Функция fopen(). Открытие потока.
1.3.3.2. Функция fclose(). Закрытие потока.
1.3.3.9. Функции scanf() и fscanf(). Ввод данных с преобразованием формата.
2.3. Пример 3. Системный вызов write()
2.4. Пример 4. Системный вызов unlink()
Обработка файлов из программы на Си.
Порядок обработки.
При обработке файлов, важнейшими являются режимы ОТКРЫТИЯ и ЗАКРЫТИЯ файла. Эти режимы взаимоисключающие. В ОС UNIX все действия по определению режима работы с файлом устанавливаются при его открытии. Сюда входит:
Инициализация файла: трансляция имени файла в файловый дескриптор (номер) в таблице дескрипторов внутри процесса;
Создание записи в системной файловой таблице, которая содержит права доступа к файлу, текущую позицию указателя в нем и другую информацию; эта таблица общая для всех процессов.
Все эти операции проводятся автоматически при вызове open(). Ядро само создает цепочку от файлового дескриптора до inode(vnode) файла, и далее до блоков данных.
Несколько процессов могут одновременно работать с одним и тем же файлом, для этого в системной файловой таблице создаются несколько записей, ссылающихся на один и тот же файл; количество таких процессов указывается в поле f_count.
При закрытии проводятся обратные открытию действия за исключением того, что выделенное под файл физическое пространство во вторичной памяти сохраняется за ним во всех случаях, если противное не было оговорено специально при его открытии. При закрытии файла всегда осуществляется:
Запись файл всего, что не было записано и было кэшировано в оперативной памяти
Удаление дескриптора из системной и внутрипроцессной файловой таблицы
В Unix-системах нет операции удаления файла в том смысле, какой существует в Windows. Есть только удаление ссылки на узел - unlink - и ссылки на пустой каталог - rmdir. Сам же файл автоматически удаляется тогда, когда делается недоступным для системы. Это означает, что не должно остаться, во-первых, ни одной ссылки на него, а во-вторых, ни одной работающей с ним активной программы. К слову, именно поэтому в Unix/Linux можно обойтись без перезагрузки практически при любом изменении системы (за исключением замены ядра ОС). Чтобы обновить системную библиотеку, вы стираете её прежнюю версию (т.е. освобождаете соответствующую ссылку) и записываете под тем же именем новую. Ядро откладывает момент удаления библиотеки до тех пор, пока не закончит работу последняя из программ, её использующая (что может произойти спустя долгое время).
В среде программирования UNIX существуют два основных интерфейса для файлового ввода/вывода:
1.Интерфейс системных вызовов
2.Стандартная библиотека ввода/вывода
1.2. Системные вызовы и их особенности при работе с файлами.
Для работы с каким-либо файлом наша программа должна открыть этот файл - установить связь между именем файла и некоторой переменной в программе. При открытии файла в ядре операционной системы выделяется "связующая" структура file "открытый файл", содержащая:
f_offset:
указатель позиции чтения/записи, который в дальнейшем мы будем обозначать как RWptr. Это long-число, равное расстоянию в байтах от начала файла до позиции чтения/записи;
f_flag:
режимы открытия файла: чтение, запись, чтение и запись, некоторые дополнительные флаги;
f_inode:
расположение файла на диске.
При открытии файла в этой таблице ищется свободная ячейка, в нее заносится ссылка на структуру "открытый файл" в ядре, и ИНДЕКС этой ячейки выдается в вашу программу в виде целого числа - так называемого
"дескриптора файла".
При закрытии файла связная структура в ядре уничтожается, ячейка в таблице считается свободной, т.е. связь программы и файла разрывается.
Дескрипторы являются локальными для каждой программы. Т.е. если две программы открыли один и тот же файл - дескрипторы этого файла в каждой из них не обязательно совпадут (хотя и могут). Обратно: одинаковые дескрипторы (номера) в разных программах не обязательно обозначают один и тот же файл.
1.2.1. Открытие файла. Системный вызов open().
Файловый дескриптор используется в качестве параметра, описывающего поток ввода-вывода, для системных вызовов, выполняющих операции над этим потоком. Поэтому прежде чем совершать операции чтения данных из файла и записи их в файл, мы должны поместить информацию о файле в таблицу открытых файлов и определить соответствующий файловый дескриптор. Для этого применяется процедура открытия файла, осуществляемая системным вызовом open().
Прототип системного вызова
#include <fcntl.h>
int open(char *path, int flags);
int open(char *path, int flags, int mode);
Описание системного вызова
Системный вызов open предназначен для выполнения операции открытия файла и, в случае ее удачного осуществления, возвращает файловый дескриптор открытого файла (небольшое неотрицательное целое число, которое используется в дальнейшем для других операций с этим файлом).
Параметр path является указателем на строку, содержащую полное или относительное имя файла.
Параметр flags может принимать одно из следующих трех значений:
O_RDONLY – если над файлом в дальнейшем будут совершаться только операции чтения;
O_WRONLY – если над файлом в дальнейшем будут осуществляться только операции записи;
O_RDWR – если над файлом будут осуществляться и операции чтения, и операции записи.
Каждое из этих значений может быть скомбинировано посредством операции "побитовое или ( | )" с одним или несколькими флагами:
O_CREAT – если файла с указанным именем не существует, он должен быть создан;
O_EXCL – применяется совместно с флагом O_CREAT. При совместном их использовании и существовании файла с указанным именем, открытие файла не производится и констатируется ошибочная ситуация;
O_NDELAY – запрещает перевод процесса в состояние ожидание при выполнении операции открытия и любых последующих операциях над этим файлом;
O_APPEND – при открытии файла и перед выполнением каждой операции записи (если она, конечно, разрешена) указатель текущей позиции в файле устанавливается на конец файла;
O_TRUNC – если файл существует, уменьшить его размер до 0, с сохранением существующих атрибутов файла, кроме, быть может, времен последнего доступа к файлу и его последней модификации.
O_SYNC – любая операция записи в файл будет блокироваться (т. е. процесс будет переведен в состояние ожидание) до тех пор, пока записанная информация не будет физически помещена на соответствующий нижележащий уровень hardware;
O_NOCTTY – если имя файла относится к терминальному устройству, оно не становится управляющим терминалом процесса, даже если до этого процесс не имел управляющего терминала.
Параметр mode устанавливает атрибуты прав доступа различных категорий пользователей к новому файлу при его создании. Он обязателен, если среди заданных флагов присутствует флаг O_CREAT, и может быть опущен в противном случае. Этот параметр задается как сумма следующих восьмеричных значений:
0400 – разрешено чтение для пользователя, создавшего файл;
и т.д.
При создании файла реально устанавливаемые права доступа получаются из стандартной комбинации параметра mode и маски создания файлов текущего процесса umask, а именно – они равны mode & ~umask.
Возвращаемое значение
Системный вызов возвращает значение файлового дескриптора для открытого файла при нормальном завершении и значение -1 при возникновении ошибки.
1.2.2. Закрытие файла. Системный вызов close().
Прототип системного вызова:
#include <unistd.h>
int close(int fd);
Описание системного вызова
Системный вызов close предназначен для корректного завершения работы с файлами. Он разрывает связь между файловым дескриптором и открытым файлом. Надо отметить, что при завершении работы процесса с помощью явного или неявного вызова функции exit() происходит автоматическое закрытие всех открытых потоков ввода-вывода.
Параметр fd является дескриптором соответствующего объекта.
Возвращаемое значение
Системный вызов возвращает значение 0 при нормальном завершении и значение -1 при возникновении ошибки.
-> Пример 1
1.2.3. Чтение и запись из/в файл(а). Системные вызовы read() и write().
Системные вызовы read и write предназначены для осуществления потоковых операций ввода (чтения) и вывода (записи) информации над каналами связи, описываемыми файловыми дескрипторами. При работе с файлами информация записывается в файл или читается из него, начиная с места, определяемого указателем текущей позиции в файле. Значение указателя увеличивается на количество реально прочитанных или записанных байт.
Прототипы системных вызовов
#include <sys/types.h>
#include <unistd.h>
size_t read(int fd, void *addr, size_t nbytes);
size_t write(int fd, void *addr, size_t nbytes);
Описание системных вызовов
Системные вызовы read и write предназначены для осуществления потоковых операций ввода (чтения) и вывода (записи) информации над каналами связи, описываемыми файловыми дескрипторами, т.е. для файлов, pipe, FIFO и socket.
Параметр fd является файловым дескриптором созданного ранее потокового канала связи, через который будет отсылаться или получаться информация, т. е. значением, которое вернул один из системных вызовов open(), pipe() или socket().
Параметр addr представляет собой адрес области памяти, начиная с которого будет браться информация для передачи или размещаться принятая информация.
Параметр nbytes для системного вызова write определяет количество байт, которое должно быть передано, начиная с адреса памяти addr. Параметр nbytes для системного вызова read определяет количество байт, которое мы хотим получить из канала связи и разместить в памяти, начиная с адреса addr.
Тип данных size_t обычно является синонимом типа long.
Возвращаемые значения