
- •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.9.2. Выход из системы: Как это происходит
Давайте обратимся к простому примеру. Программа, которая удаляет ваше имя из журна-I ла, должна выполнять следующие действия:
1. Открыть файл utmp.
2. Читать файл utmp до обнаружения записи о вашем терминале..
3. Сместить модифицированную запись utmp на ее место.
4. Закрыть файл utmp.
Рассмотрим эти четыре шага, один за другим.
Шаг 1: Открытие файла utmp
Программа выхода читает из файла utmp (она способна найти запись о вашем терминале), [' а также производит запись в файл utmp (чтобы заменить запись). Поэтому программа выхода должна открыть файл utmp на чтение и запись:
fd = open(UTMP.FILE, O.RDWR);
Шаг 2: Поиск записи о вашем терминале
Все происходит просто. В цикле while будут по одной читаться utmp записи (или будет использовано буферирование), будет производиться сравнение значения utjine с именем вашего терминала. Это может происходить так:
while(read(fd, rec, utmplen) == utmplen) /* получить следующую запись*/
if (strcmp(rec.utjne, myline) == 0) /* это моя линия? */
revise_entry(); /* удалить мое имя */
ШагЗ: Запись модифицированной записи на место
Программа выхода модифицирует запись и помещает эту запись обратно в файл. Программа изменяет значение USER_PROCESS, которое находится в utjype, на значение DEAD_PROCESS. В некоторых версиях программ выхода может производиться очистка поля с входным именем пользователя и поля с именем хост-машины, а значение, которое было в поле utjime заменяется на время выхода. Описанные действия легко запрограммировать.
Теперь возникает такой большой вопрос: как же мы запишем модифицированную запись [ обратно в файл? Если просто вызвать системный вызов write, то произойдет модификация [ счедующей записи. Это произойдет потому, что ядро поддерживает понятие текущей позиции в файле и смещает текущую позицию после каждого прочтения некого числа байтов или при записи в файл. При организации поиска utmp записи о нашем терминале текущая позиция была выставлена на следующую запись. Тогда возникает важный вопрос.
Вопрос: Как программа может изменить текущий указатель чтения-записи в файле?
Ответ: С помощью системного вызова lseek. Мы рассмотрим lseek в следующем разделе.
Шаг 4: Закрытие файла
Следует вызвать close(fd).
2.9.3. Смещение текущего указателя: Iseek
Unix управляет текугцим указателем в каждом открытом файле, как это показано на рисунке 2.8.
Каждый раз, когда вы читаете байты из файла, ядро будет читать данные с текущей позиции и затем смещать текущий указатель на то число байтов, которое было прочитано. Указатель используется и при записи данных в файл. Каждый раз, когда вы производите запись байтов в файл, ядро помещает их в файл, начиная с текущей позиции, а затем корректирует значение текущей позиции - увеличивает ее на число записанных байтов.
Рисунок 2.8
Каждый открытый файл имеет текущий указатель
Текущий указатель позиции привязан к соединению с файлом, а не к самому файлу. Например, если две программы открыли один и тот же файл, то после открытия для каждого соединения будет поддерживаться собственный указатель позиции. Программы могут читать или записывать в разных местах файла. Системный вызов Iseek дает вам возможность изменять текущую позицию в открытом файле и имеет такие характеристики:
Iseek |
|
НАЗНАЧЕНИЕ |
Устанавливает файловый указатель с определенным смещением в файле |
INCLUDE |
#inciude < sys/types. h > #include < unustd.h > |
ИСПОЛЬЗОВАНИЕ |
offj oldpos = Iseekfint fd, offj dist, int base) |
АРГУМЕНТЫ |
fd - дескриптор файла dist: смещение в байтах base: base: SE£K_SET => от начала файла SEEK_CUR => от текущей позиции SEEK_END => от конца файла |
КОДЫ ВОЗВРАТА |
-1 - при ошибке Или предшествующая позиция в файле |
Iseek устанавливает текущий указатель через дескриптор открытого файла fd в то место в файле, которое задается парой значений - dist и base. Значением base (база) можно задавать начало файла (0), текущую позицию в файле (1) или конец файла (2). Смещение - это число байтов относительно базы.
Например, при таком обращении к системному вызову:
Iseekffd, -(sizeof(struct utmp)), SEEK_CUR);
произойдет смещение текущего указателя на sizeof(struct utmp) байтов относительно текущей позиции. При обращении вида:
iseekffd, 10 * sizeof(struct utmp), SEEK_SET);
текущий указатель будет установлен на начало одиннадцатой utmp записи в файле. А при обращении вида:
Iseekffd, 0, SEEK_END); writeffd, "hello", strienf'hello"));
текущий указатель будет установлен в конец файла и там будет записана текстовая строка. Наконец, нотация вида: Iseek(fd, О, SEEK_CUR) означает возврат в текущую позицию.