Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учеб.пос.СП.doc
Скачиваний:
28
Добавлен:
31.03.2015
Размер:
1.33 Mб
Скачать

2.12. Системные вызовы truncate и ftruncate

Системные вызовы truncate и ftruncate используются для изменения размеров файла, как в большую, так и в меньшую сторону:

truncate - изменяет размер файла, заданного по имени:

#include <unistd.h>

int truncate (

const char *path, /* полное имя файла */

off_t length /* новый размер файла */

);

/* Возвращает 0 в случае успеха, -1 в случае ошибки (код ошибки в переменной errno) */

ftruncate - изменяет размер файла, заданного дескриптором:

#include <unistd.h>

int ftruncate (

int fd, /* дескриптор файла */

off_t length /* новый размер файла */

);

/* Возвращает 0 в случае успеха, -1 в случае ошибки (код ошибки в переменной errno) */

Ранее, до появления этих вызовов в Unix, усечение файлов было невозможным. Вызов ftruncate может использоваться для изменения блока общей памяти.

Контрольные вопросы

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

  2. С помощью системного вызова pread написать программу, которая выводит содержимое файла задом наперед.

  3. Напишите программу, которая открывает файл для записи с флагом O_APPEND и затем записывает в него текстовую строку. Запустите одновременно несколько экземпляров программы и убедитесь, что перемешивания сток не происходит.

  4. Напишите свой вариант программы cat, которая не имеет опций командной строки. Дополнительно попробуйте реализовать столько опций, сколько будет под силу.

  5. Попробуйте реализовать свою версию команды tail.

Литература

  1. Глас Г., Эйблс К. Unix для программистов и пользователей. / Г. Глас, К. Эйблс. – СПб.: БХВ-Петербург, 2004. – 848 с.: ил.

  2. Брюс М. Unix/Linux: Теория и практика программирования. / М.Брюс. – Издательство: "Кудиц-Образ", 2004. -576 с.

  3. Кофлер М. Linux. Полное руководство. / М. Кофлер. Издательство: Питер, 2011. – 800

с.

  1. Собель М.Г. Linux. Администрирование и системное программирование. / М.Г. Собель. - Издательство: Питер, 2011. – 880 с.

Глава 3. Дополнительные операции файлового ввода_вывода

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

    1. Низкоуровневый доступ к файловой системе

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

Начинается файловая система суперблоком, расположенным на фиксированном расстоянии от начала дискового раздела. Суперблок содержит разнообразную информацию о файловой системе: количество индексных узлов, объем дискового раздела в блоках, заголовок связного списка свободных блоков и тому подобное. Каждый файл имеет свой индексный узел и должен быть связан как минимум с одним из каталогов. Файлы, которые хранят некоторые данные, обычные файлы, каталоги и символические ссылки – могут занимать несколько дисковых блоков, указатель на список блоков, принадлежащих файлу, также хранится в индексном узле. Индексные узлы располагаются в месте, определяемом суперблоком. Индексные узлы с номерами 0 и 1 не используются. Индексный узел с номером 2 зарезервирован под корневой каталог (/) файловой системы. Остальные номера индексных узлов не имеют предопределенного назначения и могут быть использованы без каких-либо ограничений.

Уметь обращаться с суперблоком через плоский файл устройства при помощи системного вызова read бывает довольно полезным, но для этих целей лучше пользоваться специальными системными вызовами statrvfs и fstatvfs:

statrvfs - возвращает сведения о файловой системе по имени каталога

#include <sys/statvfs.h>

int statvfs(

const char *path, /* путь к файловой системе */

struct statvfs *buf /* возвращаемые сведения */

);

/* Возвращает 0 в случае успеха, -1 в случае ошибки (код ошибки в переменной errno) */

fstatrvfs - возвращает сведения о файловой системе по дескриптору файла

#include <sys/statvfs.h>

int fstatvfs(

const int fd, /* дескриптор файла */

struct statvfs *buf /* возвращаемые сведения */

);

/* Возвращает 0 в случае успеха, -1 в случае ошибки (код ошибки в переменной errno) */

На практике наиболее часто используется вызов statrvfs, который возвращает сведения о файловой системе, расположенной по указанному пути. Однако, если в программе имеется открытый файл, можно воспользоваться вызовом fstatrvfs, который вернет те же самые сведения.

Стандарты определяют полный перечень полей структуры statrvfs, но каждая конкретная реализация не обязана поддерживать их все. За более точной информацией по этому вопросу следует обратиться к страницам справочного руководства (man). Если в вашем случае какие-либо из стандартных полей не поддерживаются, то это значит, что на их месте находятся поля с информацией иного характера:

struct statvfs - структура, используемая при обращении к statrvfs и fstatrvfs

struct statvfs {

unsigned long f_bsize; /* размер блока */

unsigned long f_frsize; /* фундаментальный размер блока (fblock) */

fsblkcnt_t f_blocks; /* общее число блоков fblock */

fsblkcnt_t f_bfree; /* количество свободных блоков для суперпользователя */

fsblkcnt_t f_bavail; /* количество свободных блоков для пользователя */

fsfilcnt_t f_files; /* общее количество индексных узлов */

fsfilcnt_t f_ffree; /* количество свободных индексных узлов

для суперпользователя */

fsfilkcnt_t f_favail; /* количество свободных индексных узлов для пользователя */

unsigned long f_fsid; /* идентификатор файловой системы */

unsigned long f_flag; /* флаги */

unsigned long f_namemax; /* максимальная длина имени файла */

};

Некоторые замечания по этой структуре:

  • чтобы повысить скорость доступа, большинство файловых систем выделяют файлам блоки большого размера, который задается полем f_bsize, но конец файла размещается в блоках маленького размера с целью экономии дискового пространства. Размер таких блоков-фрагментов называется фундаментальным и хранится в поле f_frsize (сокращенно такие блоки называются fblock. Поля структуры, имеющие тип fsblkcnt_t, хранят количество фрагментов блоков. Чтобы получить величину, выраженную в байтах, необходимо имеющееся там значение умножить на фундаментальный размер блока (f_frsize);

  • типы fsblkcnt_t и fsfilcnt_t являются беззнаковыми, но от реализации к реализации размер их может отличаться;

  • спецификации SUS определяют всего два флага для поля f_flag - они информируют о том, как была смонтирована файловая система: ST_RDONLY - только для чтения, ST_NOSUID - в целях безопасности отключена возможность изменения прав доступа для исполняемых файлов;

  • В большинстве систем для нужд суперпользователя выделяется немного больше пространства, чем для обычного пользователя. Таким способом создается минимально необходимый резерв на случай отсутствия свободного места в файловой системе.