Опубликован: 16.09.2004 | Уровень: специалист | Доступ: свободно | ВУЗ: Московский физико-технический институт
Лекция 8:

Организация файловой системы в UNIX. Работа с файлами и директориями. Понятие о memory mapped файлах

Операции изменения атрибутов файла. Большинство операций изменения атрибутов файла обычно выполняется пользователем в интерактивном режиме с помощью команд операционной системы. О них уже шла речь в материалах семинаров 1–2, и мы не будем возвращаться к ним вновь. Отметим только операцию изменения размеров файла, а точнее операцию его обрезания, без изменения всех других атрибутов, кроме, быть может, времени последнего доступа к файлу и его последней модификации. Для того чтобы уменьшить размеры существующего файла до 0, не затрагивая остальных его характеристик (прав доступа, даты создания, учетной информации и т.д.), можно при открытии файла использовать в комбинации флагов системного вызова open() флаг O_TRUNC. Для изменения размеров файла до любой желаемой величины (даже для его увеличения во многих вариантах UNIX, хотя изначально этого не предусматривалось!) может использоваться системный вызов ftruncate() . При этом, если размер файла мы уменьшаем, то вся информация в конце файла, не влезающая в новый размер, будет потеряна. Если же размер файла мы увеличиваем, то это будет выглядеть так, как будто мы дополнили его до недостающего размера нулевыми байтами.

Системный вызов ftruncate()

Прототип системного вызова

#include <sys/types.h>
#include <unistd.h>
int ftruncate(int fd, size_t length);

Описание системного вызова

Системный вызов ftruncate предназначен для изменения длины открытого регулярного файла.

Параметр fd является дескриптором соответствующего файла, т. е. значением, которое вернул системный вызов open() .

Параметр length – значение новой длины для этого файла. Если параметр length меньше, чем текущая длина файла, то вся информация в конце файла, не влезающая в новый размер, будет потеряна. Если же он больше, чем текущая длина, то файл будет выглядеть так, как будто мы дополнили его до недостающего размера нулевыми байтами.

Возвращаемое значение

Системный вызов возвращает значение 0 при нормальном завершении и значение -1 при возникновении ошибки.

Операции чтения из файла и записи в файл. Для операций чтения из файла и записи в файл применяются системные вызовы read() и write() , которые мы уже обсуждали ранее (семинар 5, раздел "Системные вызовы read() , write() , close() ").

Надо отметить, что их поведение при работе с файлами имеет определенные особенности, связанные с понятием указателя текущей позиции в файле.

При работе с файлами информация записывается в файл или читается из него, начиная с места, определяемого указателем текущей позиции в файле. Значение указателя увеличивается на количество реально прочитанных или записанных байт. При чтении информации из файла она не пропадает из него. Если системный вызов read возвращает значение 0, то это означает, что достигнут конец файла.

Операция изменения указателя текущей позиции. Системный вызов lseek() . С точки зрения процесса все регулярные файлы являются файлами прямого доступа. В любой момент процесс может изменить положение указателя текущей позиции в открытом файле с помощью системного вызова lseek() .

Особенностью этого системного вызова является возможность помещения указателя текущей позиции в файле за конец файла (т.е. возможность установления значения указателя большего, чем длина файла).

При любой последующей операции записи в таком положении указателя файл будет выглядеть так, как будто возникший промежуток от конца файла до текущей позиции, где начинается запись, был заполнен нулевыми байтами. Если операции записи в таком положении указателя не производится, то никакого изменения файла, связанного с необычным значением указателя, не произойдет (например, операция чтения будет возвращать нулевое значение для количества прочитанных байтов).

Системный вызов lseek()

Прототип системного вызова

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, 
            int whence);

Описание системного вызова

Системный вызов lseek предназначен для изменения положения указателя текущей позиции в открытом регулярном файле.

Параметр fd является дескриптором соответствующего файла, т. е. значением, которое вернул системный вызов open() .

Параметр offset совместно с параметром whence определяют новое положение указателя текущей позиции следующим образом:

  • Если значение параметра whence равно SEEK_SET, то новое значение указателя будет составлять offset байт от начала файла. Естественно, что значение offset в этом случае должно быть не отрицательным.
  • значение параметра whence равно SEEK_CUR, то новое значение указателя будет составлять старое значение указателя + offset байт. При этом новое значение указателя не должно стать отрицательным.
  • Если значение параметра whence равно SEEK_END, то новое значение указателя будет составлять длина файла + offset байт. При этом новое значение указателя не должно стать отрицательным.

Системный вызов lseek позволяет выставить текущее значение указателя за конец файла (т.е. сделать его превышающим размер файла). При любой последующей операции записи в этом положении указателя файл будет выглядеть так, как будто возникший промежуток был заполнен нулевыми битами.

Тип данных off_t обычно является синонимом типа long.

Возвращаемое значение

Системный вызов возвращает новое положение указателя текущей позиции в байтах от начала файла при нормальном завершении и значение -1 при возникновении ошибки.

Операция добавления информации в файл. Флаг O_APPEND. Хотя эта операция по сути дела является комбинацией двух уже рассмотренных операций, мы считаем нужным упомянуть ее особо. Если открытие файла системным вызовом open() производилось с установленным флагом O_APPEND, то любая операция записи в файл будет всегда добавлять новые данные в конец файла, независимо от предыдущего положения указателя текущей позиции (как если бы непосредственно перед записью был выполнен вызов lseek() для установки указателя на конец файла).

лия логовина
лия логовина

организовать двустороннюю поочередную связь процесса-родителя и процесса-ребенка через pipe, используя для синхронизации сигналы sigusr1 и sigusr2.

Макар Оганесов
Макар Оганесов
Сергей Пархоменко
Сергей Пархоменко
Россия, Ростов-на-Дону, ЮФУ (ДГТУ), 2008