
- •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.6.3. Вопрос 3: Могу ли я написать программу ср?
Проверим, насколько было все понятно, путем создания версии программы ср. Схема работы программы будет такой:
открытие исходного файла для чтения
открытие целевого файла на запись
+
->
чтение из исходного файла в буфер -•
eof?
-+
| _ запись из буфера в файл
закрыть исходный файл <.............+
закрыть целевой файл
На рисунке 2.4 показаны потоки данных при копировании:
Рисунок 2.4
Копирование файлов посредством чтения и записи
Файлы расположены на диске. Исходный файл находится слева на схематическом изображении диска, а целевой файл - справа. Буфер представляет собой область памяти в пределах среды процесса. Процесс располагает двумя файловыми дескрипторами. Данные читаются из исходного файла в буфер, а затем записываются из буфера в целевой файл.
Наконец, программный код, который соответствует изображению на рисунке, будет таким:
/**ср1.с
* версия 1 программы ср - использует read и write при работе с буфером с
* настраиваемым размером
*
* usage: cp1 src dest
*/
include <stdio.n>
#include <unistd.h>
#include <fcntl.h>
#define BUFFERSIZE 4096
#define COPYMODE 0644
void oops(char *, char *);
mainfintac, char*avfj)
(
int in_fd, out fd, n chars;
charbuffBUFFERSIZE];
I* проверка аргументов */
if(ac!=3){
fprintf(stderr, "usage: %s source destination\n", *av);
exit(1);
}
I* открытие файлов */
if ((in_fd=open(av[1], O.RDONLY)) == -1)
oops(“Cannot open", av[1]);
if ((out_fd=creat(av[2], COPYMODE)) == -1}
oopsf'Cannot creat", av[2]);
/* копирование файлов */
while ((n_chars = readfinjd, buf, BUFFERSIZE)) > 0)
if (write(out_fd, buf, n_chars) != nchars)
oops(Write error to", av[2]);
if (n_chars == -1)
oopsf'Read error from ", av[1]);
I* закрытие файлов */
if (close(injd) == -11| close(outjd) == -1)
oops('Error closing files","");
}
void oopsfchar *s1, char *s2)
{
fprintf(stderr,"Error: %s", s1);
perror(s2);
exit(1);
}
Откомпилируем и проверим работу программы:
$ сс ср1.с -оср1
$ ср1 ср1 copy.of.cp1
$ Is -»ср1 copy.of.cp1
-rw-r-r- 1 brucebruce 37419 Jul 23 03:12 copy.of.cp1
-rwxrwxr-x 1 bruce bruce 37419 Jul 23 03:08 cp1
$ cmp cp1 copy.of.cp1
$
С первого взгляда кажется, что все работает. Утилита cmp сравнивает два файла и при обнаружении несовпадения по содержанию оповещает об этом. Поскольку разницы между указанными файлами нет, то нет и сообщения о несовпадении.
А как наша программа будет реагировать на ошибочные ситуации? Сначала попытаемся снять копию с несуществующего файла, а затем записать копию в каталог. Получим такой результат:
$ср1 xxx123 file1
Error: Cannot open xxx123; No such file or directory
$ cp1 cp1 /tmp
Error: Cannot creat Amp: Is a directory
Проверим другие ошибочные ситуации. Следует обратиться к документации по системному вызову и посмотреть там, какие ошибки могут возникать при его выполнении. Затем нужно попытаться воспроизвести ошибочные ситуации. При этом проверяйте - не затираете ли вы файлы, с которыми вам будет необходимо работать.