- •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.3. Написание программы who 1.С
Итак, мы почти у цели. Мы знаем суть работы команды who, мы знаем о существовании трех системных вызовов, необходимых для установления связи с файлом, выбора данных из файла и для закрытия файла. Ведущая часть кода программы будет выглядеть так:
/* whol .с - первая версия программы who
* выполнить open, прочитать файл UTMP и показать результаты
7
#include <stdio.h>
#include <utmp.h>
«include <fcntl.h>
«include <unistd.h>
«define SHOWHOST /* подключить удаленную машину для вывода*/
Iint main()
{
struct utmp currentjecord; f* считывать сюда данные */
int utmpfd; /* читать из этого дескриптора */
int reclen = sizeof(currentjecord);
if ((utmpfd = open(UTMPFILE, O.RDONLY)K== -1){
perrorfUTMP FILE); /* UTMP FILE - описание в utmp.h */
exit(1);
}
(while (read(utmpfd, ¤t_ record, reclen) == reclen)
Show_jnfo( ¤t_record);
close(utmpfd);
return 0; /* все нормально */
}
В этой программе реализована логика, которая была рассмотрена выше в этой главе. В цикле while производится последовательное чтение записей из файлового дескриптора currentjecord. Функция showinfo отображает информацию о вхождениях в систему. Программа работает в цикле до тех пор, пока системный вызов read в состоянии читать записи из файла. Наконец, происходит закрытие файла и выход из программы.
Системный вызов perror является удобным средством для оповещения о наличии системных ошибок. Мы рассмотрим его далее в этой главе.
2.5.4. Отображение записей о вхождениях в систему
Далее приведен код первого наброска функции show_info, которая производит отображение информации из файла utmp.
/*
* show_info()
* отображает содержимое структуры utmp в формате, удобном для восприятия
* эти размеры аппаратно не зашиты
*/
show_info(struct utmp *utbufp)
{
printf("%-8.8s", utbufp->ut_name); |
/* входное имя */ |
printf(""); |
/* пробел */ |
printf("%-8.8s", utbufp->ut_line); |
/* терминал */ |
printff'"); |
/*пробел */ |
printf("%10ld", utbufp->ut time); |
/* время вхождения */ |
prtntf(""); |
Г пробел */ |
#ifdefSHOWHOST |
|
printf("(%s)", utbufp->ut_host); |
/* хост */ |
#endif |
|
printf("\n”); |
/* перевод на новую строку */ |
Мы выбрали в этой программе ширину полей для printf так, чтобы было соответствие с длинами строк вывода системной версии программы^ who. Программа выводит элемент utjime в формате long int. Значение time_t определено в/ заголовочном файле, но мы пока ничего об этом не знаем. У
Компилируем и запускаем программу на исполнение:
$ccwho1.c-owho1
$who1
system b |
9526014110 |
run-leve |
9526014110 |
|
9526014160 |
|
952601416 0 |
|
952601417 0 |
|
952601417 0 |
|
9526014190 |
|
9526014190 |
|
952601423 () |
|
952601566 0 |
LOGIN console |
952601566 0 |
ttypl |
958240622 0 |
shpyrko ttyp2 |
964318862 (nas1-093.gas.swamp.org) |
acotton ttyp3 |
964319088 (math-guest04.williams.edu) |
ttyp4 |
964320298 0 |
spradlin ttyp5 |
963881486 (h002078c6adfb.ne.rusty.net) |
dkoh ttyp6 |
964314388(128.103.223.110) |
spradlin ttyp7 |
964058662 (h002078c6adfb.ne.rusty.net) |
king ttyp8 |
964279969 (blade-runner.mit.edu) |
berschba ttyp9 |
964188340 (dudley.learned.edu) |
rserved ttypa |
963538145 (gigue.eas.ivy.edu) |
dabel ttypb |
964319455 (roam 193-27.student.state.edu) |
ttypc |
964319645 0 |
rserved ttypd |
963538287 (gigue.eas.ivy.edu) |
dkoh ttype |
964298769(128:103.223.110) |
ttypf |
964314510 0 |
molay ttyqO |
964310621 (xyz73-200.harvard.edu) |
ttyql |
964311665 0 |
ttyq2 |
964310757 0 |
ttyq3 |
964304284 () |
ttyq4 |
964305014 0 |
ttyq5 |
964299803 () |
ttyq6 |
964219533 0 |
ttyq7 |
964215661 () |
cweiner ttyq8 |
964212019 (roarn175-157.student.stats.edu) |
ttyqa 964277078 () |
|
ttyq9 964231347 0 |
|
$
Давайте сравним вывод нашей программы с выводом системной версии команды who:
$who |
||
shpyrko ttyp2Jul |
22 22:21 |
(nasi -093.gas.swamp.edu) |
acotton ttyp3 Jul |
22 22:24 |
(math-guest04.williams.edu) |
spradlin ttyp5Jul |
17 20:51 |
(h002078c6adfb.ne.rusty.net) |
dkoh ttyp6 Jul |
22 21:06 |
(128.103.223.110) |
spradlin ttyp7Jul |
19 22:04 |
(h002078c6adfb.ne.rusty.net) |
king ttyp8 Jul |
22 11:32 |
(blade-runner.mit.edu) |
berschba ttyp9 Jul |
21 10:05 |
(dudley.learned.edu) |
rserved ttypa Jul |
13 21:29 |
(gigue.eas.ivy.edu) |
dabel ttypb Jul |
22 22:30 |
(roam I53-27.student.state.edu) |
rserved ttypd Jul |
13 21:31 |
(gigue.eas.harvard.edu) |
dkoh ttype Jul |
22 16:46 |
(128.103.223.110) |
molay ttyqO Jul |
2220:03 |
(xyz73-200.harvard.edu) |
cweiner ttyq8 Jul |
21 16:40 |
(roam175- 157.student.stats.edu) |
$
Наша версия выглядит как перспективная, но все еще не в полном виде. Есть еще шероховатости, которые следует ликвидировать. У нас выводятся те же пользовательские имена,
как и в who. У нас выводятся правильные имена терминалов, правильно указываются имена удаленных машин. Но есть две проблемы.
Что нам следует еще сделать:
■ Подавить пустые записи.
■ Получить корректное представление времени вхождения в систему.
