• Системные вызовы read()
и write()
соответственно читают и записывают данные. Их интерфейс прост. В частности, они не интерпретируют данные, файлы представлены линейными потоками байтов. Системный вызов lseek()
осуществляет ввод/выводе произвольным доступом: возможность перемещаться внутри файла.
• Для синхронного ввода/вывода предусмотрены дополнительные флаги для open()
, при этом данные записываются на физический носитель данных до возвращения write()
или read()
. Можно также форсировать запись данных на диск на управляемой основе с помощью fsync()
или fdatasync()
.
• Системные вызовы truncate()
и ftruncate()
устанавливают абсолютную длину файла. (На более старых системах они могут использоваться лишь для сокращения длины файла; на современных системах они могут также увеличивать файл.)
Упражнения
1. Используя лишь open()
, read(),
write()
и close()
, напишите простую программу copy
, которая копирует файл, имя которого дается в первом аргументе, в файл с именем во втором аргументе.
2. Усовершенствуйте программу copy
так, чтобы она принимала "-
" в значении «стандартный ввод» при использовании в качестве первого аргумента и в значении «стандартный вывод» в качестве второго аргумента. Правильно ли работает 'copy - -
'?
3. Просмотрите страничку справки для 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
'.
Глава 5
Каталоги и служебные данные файлов
Данная глава продолжает подъем по кривой обучения до следующего плато: понимания каталогов и информации о файлах.
В данной главе мы исследуем то, как информация хранится в каталоге, как читаются, создаются и удаляются сами каталоги, какая информация о файлах доступна и как ее получить. Наконец, мы рассмотрим другие способы обновления служебных данных файлов, таких, как владелец, группа, права доступа и время доступа и изменения файла.
5.1. Просмотр содержимого каталога
Все Unix-системы, включая Linux, используют для хранения файловой информации на диске один и тот же концептуальный дизайн. Хотя в реализации дизайна есть значительные вариации, интерфейс на уровне С остается постоянным, давая возможность писать переносимые программы, которые компилируются и запускаются на многих различных системах.
5.1.1. Определения
Рис. Copyright 1997-2004 © J.D. «Illiad» Frazer. Использовано по разрешению, http://www.userfriendly.org
Мы начнем обсуждение с определения нескольких терминов.
Единица физического хранилища.