Linux программирование в примерах - Роббинс Арнольд
Шрифт:
Интервал:
Закладка:
• Системные вызовы read() и write() соответственно читают и записывают данные. Их интерфейс прост. В частности, они не интерпретируют данные, файлы представлены линейными потоками байтов. Системный вызов lseek() осуществляет ввод/выводе произвольным доступом: возможность перемещаться внутри файла.
• Для синхронного ввода/вывода предусмотрены дополнительные флаги для open(), при этом данные записываются на физический носитель данных до возвращения write() или read(). Можно также форсировать запись данных на диск на управляемой основе с помощью fsync() или fdatasync().
• Системные вызовы truncate() и ftruncate() устанавливают абсолютную длину файла. (На более старых системах они могут использоваться лишь для сокращения длины файла; на современных системах они могут также увеличивать файл.)
Упражнения
1. Используя лишь open(), read(), write() и close(), напишите простую программу copy, которая копирует файл, имя которого дается в первом аргументе, в файл с именем во втором аргументе.
2. Усовершенствуйте программу copy так, чтобы она принимала "-" в значении «стандартный ввод» при использовании в качестве первого аргумента и в значении «стандартный вывод» в качестве второго аргумента. Правильно ли работает 'copy - -'?
3. Просмотрите страничку справки для proc(5) на системе GNU/Linux. В частности, посмотрите подраздел fd. Выполните 'ls -l /dev/fd' и непосредственно проверьте файлы в /proc/self/fd. Если бы /dev/stdin и дружественные устройства были бы в ранних версиях Unix, как это упростило бы код для программы V7 cat? (Во многих других современных системах Unix есть каталог или файловая система /dev/fd. Если вы не используете GNU/Linux, посмотрите, что вы можете обнаружить в своей версии Unix.)
4. Даже если вы пока этого не понимаете, постарайтесь скопировать сегмент кода из V7 cat.c, который использует struct stat и функцию fstat(), в ch04-cat.c, чтобы она также сообщала об ошибке для 'cat file >> file'.
5. (Простое) Предположив наличие strerror(), напишите свою версию perror().
6. Каков результат выполнения 'ulimit -n' на вашей системе?
7. Напишите простую версию программы umask, назвав ее myumask, которая принимает в командной строке восьмеричную маску. Используйте strtol() с основанием 8 для преобразования строки символов аргумента командной строки в целое значение. Измените umask с помощью системного вызова umask().
Откомпилируйте и запустите myumask, затем проверьте значение umask с помощью стандартной команды umask. Объясните результаты. (Подсказка: в оболочке Bash введите 'type umask'.)
8. Измените простую программу copy, которую вы написали ранее, для использования open() с флагом O_SYNC. Используя команду time, сравните характеристики первоначальной и новой версии большого файла.
9. Мы сказали, что для ftruncate() файл должен быть открыт для записи. Как можно открыть файл для записи, когда у самого файла нет доступа записи?
10. Напишите программу truncate, которая используется следующим образом: 'truncate <i>длина_файла</i>'.
Глава 5
Каталоги и служебные данные файлов
Данная глава продолжает подъем по кривой обучения до следующего плато: понимания каталогов и информации о файлах.
В данной главе мы исследуем то, как информация хранится в каталоге, как читаются, создаются и удаляются сами каталоги, какая информация о файлах доступна и как ее получить. Наконец, мы рассмотрим другие способы обновления служебных данных файлов, таких, как владелец, группа, права доступа и время доступа и изменения файла.
5.1. Просмотр содержимого каталога
Все Unix-системы, включая Linux, используют для хранения файловой информации на диске один и тот же концептуальный дизайн. Хотя в реализации дизайна есть значительные вариации, интерфейс на уровне С остается постоянным, давая возможность писать переносимые программы, которые компилируются и запускаются на многих различных системах.
5.1.1. Определения
Рис. Copyright 1997-2004 © J.D. «Illiad» Frazer. Использовано по разрешению, http://www.userfriendly.org
Мы начнем обсуждение с определения нескольких терминов.
Раздел (partition)
Единица физического хранилища. Физические разделы обычно являются либо частями диска, либо целым диском. Современные системы дают возможность создавать из нескольких физических логические разделы.
Файловая система (filesystem)
Раздел (физический или логический), содержащий данные файла и служебные данные (metadata), информацию о файлах (в противоположность содержимому файла, которое является информацией в файле). Такие служебные данные включают владельца файла, права доступа, размер и т.д., а также информацию, использующуюся операционной системой при поиске содержимого файла. Файловые системы размещаются «в» разделах (соотношение одни к одному) посредством записи в них стандартной информации. Это осуществляется программой уровня пользователя, такой, как mke2fs в GNU/Linux или newfs в Unix. (Команда Unix mkfs создает разделы, но ее трудно использовать, непосредственно, newfs вызывает ее с нужными параметрами. Если ваша система является системой Unix, подробности см. в справочных страницах для newfs(8) и mkfs(8).)
Большей частью GNU/Linux и Unix скрывают наличие файловых систем и разделов. (Дополнительные подробности приведены в разделе 8.1 «Монтирование и демонтирование файловых систем».) Доступ ко всему осуществляется через пути, безотносительно к тому, на каком диске расположен файл. (Сравните это с почти любой коммерческой операционной системой, такой, как OpenVMS, или с поведением по умолчанию любой системы Microsoft.)