
- •2.1. Введение
- •2.2. Вопросы, относящиеся к команде who
- •2.2.1. Программы состоят из команд
- •2.3. Вопрос 1: Что делает команда who?
- •2.3.1. Обращение к справочнику
- •2.4. Вопрос 2: Как работает команда who?
- •2.4.1. Мы теперь знаем, как работает who
- •2.5. Вопрос 3: Могу ли я написать who?
- •2.5.1. Вопрос: Как я буду читать структуры из файла?
- •2.5.2. Ответ: Использование open, read и close
- •2.5.3. Написание программы who 1.С
- •2.5.4. Отображение записей о вхождениях в систему
- •2.5.5. Написание версии who2.С
- •2.6. Проект два: Разработка программы ср (чтение и запись)
- •2.6.1. Вопрос 1: Что делает команда ср?
- •2.6.2. Вопрос 2: Как команда ср создает файл и как пишет в него? Создание/транкатенация файла
- •2.6.3. Вопрос 3: Могу ли я написать программу ср?
- •2.6.4. Программирование в Unix кажется достаточно простым
- •2.7. Увеличение эффективности файловых операций ввода/ вывода: Буферирование
- •2.7.1. Какой размер буфера следует считать лучшим?
- •2.7.2 Почему на системные вызовы требуется тратить время?
- •2.7.3. Означает ли, что наша программа who2.С неэффективна?
- •2.7.4. Добавление буферирования к программе who2.С
- •2.8. Буферизация и ядро
- •2.8.1. Если буферизация столь хороша, то почему ее не использует ядро?
- •2.9. Чтение файла и запись в файл
- •2.9.1. Выход из системы: Что происходит?
- •2.9.2. Выход из системы: Как это происходит
- •2.9.3. Смещение текущего указателя: Iseek
- •2.9.4. Кодирование выхода из системы через терминал
- •2.10. Что делать с ошибками системных вызовов?
- •3.1. Введение
- •3.2. Вопрос 1: Что делает команда is?
- •3.2.1. Команда Is выводит список имен файлов и оповещает об атрибутах файлов
- •3.2.3. Наиболее употребимые опции
- •3.2.4. Первый ответ: Итоговые замечания
- •3.3. Краткий обзор дерева файловой системы
- •3.4. Вопрос 2: Как работает команда Is?
- •3.4.1. Что же такое каталог, в конце концов?
- •3.4.2. Работают ли системные вызовы open, read и close в отношении каталогов?
- •3.4.3. Хорошо, хорошо. Но как же мне прочитать каталог?
- •3.5. Вопрос 3: Могу ли я написать Is?
- •3.5.1. Что еще нужно делать?
- •3.6. Проект 2: Написание версии Is -I
- •3.6.1. Вопрос 1: Что делает Is-I?
- •3.6.2. Вопрос 2: Какработает Is -I?
- •3.6.3. Ответ: Системный вызов stat получает информацию о файле
- •3.6.4. Какую еще информацию можно получить с помощью системного вызова stat?
- •3.6.5. Чего мы достигли?
- •3.6.6. Преобразование числового значения поля mode в символьное значение
- •3.6.7. Преобразования числового представления идентификаторов собственника/группы в строковое представление
- •3.6.8. Объединение всего вместе: Is2.C
- •3.7. Три специальных разряда
- •3.7.1. Разряд Set-User-id
- •3.7.2Разряд Set-Group-id
- •3.7.3 Разряд Sticky Bit
- •3.7.4. Специальные разряды nls-l
- •3.8. Итоги для команды is
- •3.9. Установка и модификация свойств файла
- •3.9.1. Тип файла
- •3.9.2. Разряды прав доступа и специальные разряды
- •3.9.3. Число ссылок на файл
- •3.9.4. Собственник и группа для файла
- •3.9.5. Размер файла
- •3.9.6. Время последней модификации и доступа
- •3.9.7. Имя файла
2.5.2. Ответ: Использование open, read и close
Мы можем использовать эти три системных вызова для извлечения из файла utmp записей о вхождениях в систему. Страницы справочника, касающиеся этих тем, могут быть весьма краткими по содержанию. Эти системные вызовы имеют много опций и достаточно сложны в своем поведении, когда они используются в отношении программных каналов, устройств и других источников данных. Основополагающие факторы выделяются и рассматриваются далее.
Открытие файла: open
Системный вызов open создает связь между процессом и файлом. Эта связь называется дескриптором файла и изображается на рисунке 2.3 в виде туннеля от процесса к ядра
Рисунок 2.3
Дескриптор файла - это соединение с файлом.
Основные свойства системного вызова open:
ореn |
|
НАЗНАЧЕНИЕ |
Создания связи с файлом |
INCLUDE |
«include <fcntl.h> |
ИСПОЛЬЗОВАНИЕ |
int fd = open(char *name, int how) |
АРГУМЕНТЫ |
name - имя файла how - 0_RDONLY, 0_WRONLY или 0_RDWR |
КОДЫ ВОЗВРАТА |
-1 -при ошибке Целое число - при успехе |
Для открытия файла необходимо определить имя файла и тип желаемой связи. Существуют три типа связей - соединение для чтения, соединение для записи и соединение ддя \ чтения и записи. В заголовочном файле /usr/includeAcntl.h находятся определения для [ макросов 0_RDONLY, 0_WRONLY и 0_RDWR.
Открытие файлов - это служба ядра. Системный вызов open - это требование, которое выдает ваша программа ядру. Если ядро обнаружит ошибку при обращении к нему, то оно вернет код возврата, равный -1.
Есть несколько видов ошибок. Может случиться, что указанный файл не существует. Файл может существовать, но у вас нет прав доступа на чтение из этого файла. Файл может : находиться в каталоге, к которому у вас нет доступа. В странице документации по системному вызову open приведен список подобного рода ошибок. Способы обработки ошибок будут изучены далее в этой главе.
Что происходит, если файл уже был открыт? То есть что будет в ситуации, когда другой процесс уже работает с файлом? В'Unix не устанавливается запрета на одновременное открытие несколькими процессами одного и того же файла. Если бы такое ограничение существовало, то двум различным процессам нельзя было бы запустить одновременно одну и ту же команду who. Если открытие происходит успешно, то ядро возвращает процессу небольшое по значению целое положительное число. Это число называют дескриптором файла, который является по смыслу идентификатором соединения процесса с файлом.
Вы можете одновременно открыть несколько файлов. При этом для каждого соединения будет установлен уникальный дескриптор файла. Ваша программа даже может многократно отрыть один и тот же файл. При этом для каждого соединения будет установлен свой дескриптор файла.
Вы можете использовать дескриптор файла для всех операций с установленным соединением.
Чтение данных из файла: read
Вы можете в процессе производить чтение данных, используя дескриптор файла:
read |
|
НАЗНАЧЕНИЕ |
Пересылка qty байт из файлового дескриптора fd в буфер |
INCLUDE |
#include <unistd.h> |
ИСПОЛЬЗОВАНИЕ |
ssizej numread = readfint fd, void *buf, sizej qty) |
АРГУМЕНТЫ |
fd - источник данных buf - место для сохранения данных qty - количество байт для передачи |
КОДЫ ВОЗВРАТА |
-1 -при ошибке Целое число - при успехе |
С помощью системного вызова read происходит обращение к ядру для передачи qty байтов данных из файлового дескриптора fd в массив buf, которой находится в пространстве памяти вызывающего процесса. Ядро выполняет действие по запросу и возвращает информацию о результате выполнения. Если требование не было выполнено, то код возврата будет равным -1. В противном случае в качестве кода возврата будет число байтов, переданных при чтении.
Почему можно получить в ответ меньшее число байтов, чем было запрошено? В файле может не быть столько байтов, сколько вы указали при обращении к системному вызову. Например, если вы запросили 1000 байтов, а в файле содержится только 500 байтов, то после выполнения вызова вы увидите в качестве результата 500 байтов. При достижении конца файла системный вызов вырабатывает код возврата, равный нулю, поскольку нет данных для чтения.
Какового сорта ошибки может фиксировать системный вызов read? Ответ можно найти на странице документации в вашей системе, где приведен перечень ошибок.
Закрытие файла: close
Когда вы прочитали данные или записали данные через файловый дескриптор, то вы можете закрыть его. Системный вызов close представлен такими характеристиками:
close |
|
НАЗНАЧЕНИЕ |
Закрытие файла |
INCLUDE |
«include <unistd.h> |
ИСПОЛЬЗОВАНИЕ |
int result = closefint fd) |
АРГУМЕНТЫ |
fd - дескриптор данных buf - место для сохранения данных qty - количество байт для передачи |
КОДЫ ВОЗВРАТА |
-1 -при ошибке 0 - при успехе |
Системный вызов close отключает соединение, которое было определено с помощью файлового дескриптора fd. При обнаружении ошибки системный вызов close возвращает код возврата-1. Например, при попытке закрыть файловый дескриптор, который не ссылается на открытый файл, будет выработана ошибка. Другие виды ошибок описаны в справочнике.