
- •Введение
- •Глава 1. Фундаментальные концепции unix Систем
- •Программы, процессы и потоки
- •Сигналы
- •Идентификаторы процессов, группы процессов и сеансы
- •Система прав
- •Другие атрибуты процесса
- •Межпроцессное взаимодействие
- •Использование системных вызовов
- •Краткие описания функций и обработка ошибок
- •Контрольные вопросы
- •Литература
- •Глава 2. Базовые операции ввода-вывода
- •Файловые операции ввода - вывода
- •Стандартные дескрипторы
- •Системные вызовы open и creat
- •Системный вызов umask
- •Системный вызов unlink
- •Текущая позиция в файле
- •Системный вызов write
- •2.8. Системный вызов read
- •2.9. Системный вызов close
- •2.10. Системный вызов lseek
- •2.11. Системные вызовы pread и pwrite
- •2.12. Системные вызовы truncate и ftruncate
- •Контрольные вопросы
- •Литература
- •Глава 3. Дополнительные операции файлового ввода_вывода
- •Низкоуровневый доступ к файловой системе
- •Жесткие и символические ссылки
- •Системный вызов getcwd
- •Отображение метаданных файла
- •Системные вызовы getpwuid, getgrgid и getlogin
- •Каталоги
- •Системные вызовы chdir и fchdir
- •Системные вызовы mkdir и rmdir
- •Контрольные вопросы
- •Литература
- •Глава 4. Процессы и потоки
- •4.1. Среда окружения
- •Системный вызов exec
- •Системный вызов fork
- •Завершение процесса и системные вызовы exit
- •Системные вызовы wait, waitpid и waitid
- •Получение и изменение идентификаторов пользователя и группы
- •Получение и изменение приоритета
- •Контрольные вопросы
- •Литература
- •Глава 5. Механизмы межпроцессного взаимодействия
- •5.1. Каналы
- •5.2. Системные вызовы dup и dup2
- •5.3. Двунаправленное взаимодействие с использованием однонаправленных каналов
- •Контрольные вопросы
- •Литература
- •Глава 6.Механизмы взаимодействия процессов
- •Именованные каналы (fifo)
- •Системные вызовы для работы с очередями сообщений posix
- •Семафоры
- •Системные вызовы для работы с общей памятью posix
- •Контрольные вопросы
- •Литература
- •Глава 7.Сетевое взаимодействие и сокеты
- •Основные системные вызовы для работы с сокетами, образующими логические соединения
- •Обслуживание нескольких клиентов
- •Адресация сокетов
- •In_port_t sin_port; /* номер порта (uint16_t) */
- •In_addr_t s_addr; /* адрес iPv4 (uint32_t) */
- •Домен адресов af_inet6
- •In_port_t sin6_port; /* номер порта (uint16_t) */
- •Доменная система именования
- •Параметры сокетов
- •Контрольные вопросы
- •Литература
- •Глава 8.Сигналы и таймеры
- •Введение в сигналы
- •Жизненный цикл сигналов
- •Типы сигналов
- •Системный вызов sigaction
- •Контрольные вопросы
- •Литература
- •Заключение
- •Список литературы
- •Глава 2. Базовые операции ввода-вывода 14
- •Глава 3. Дополнительные операции файлового ввода_вывода 25
- •Глава 6. Механизмы взаимодействия процессов 58
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 может использоваться для изменения блока общей памяти.
Контрольные вопросы
С помощью системного вызова lseek написать программу, которая выводит содержимое файла задом наперед.
С помощью системного вызова pread написать программу, которая выводит содержимое файла задом наперед.
Напишите программу, которая открывает файл для записи с флагом O_APPEND и затем записывает в него текстовую строку. Запустите одновременно несколько экземпляров программы и убедитесь, что перемешивания сток не происходит.
Напишите свой вариант программы cat, которая не имеет опций командной строки. Дополнительно попробуйте реализовать столько опций, сколько будет под силу.
Попробуйте реализовать свою версию команды tail.
Литература
Глас Г., Эйблс К. Unix для программистов и пользователей. / Г. Глас, К. Эйблс. – СПб.: БХВ-Петербург, 2004. – 848 с.: ил.
Брюс М. Unix/Linux: Теория и практика программирования. / М.Брюс. – Издательство: "Кудиц-Образ", 2004. -576 с.
Кофлер М. Linux. Полное руководство. / М. Кофлер. Издательство: Питер, 2011. – 800
с.
Собель М.Г. Linux. Администрирование и системное программирование. / М.Г. Собель. - Издательство: Питер, 2011. – 880 с.
Глава 3. Дополнительные операции файлового ввода_вывода
Обсуждаемые здесь системные вызовы на практике используются не так широко, как те, с которыми мы познакомились в предыдущей главе. Однако знание принципов работы с ними будет далеко не лишним, потому что оно дает полное представление о принципах функционирования подсистемы ввода-вывода.
Низкоуровневый доступ к файловой системе
Информация на диске располагается в виде последовательности блоков фиксированного размера, например 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 - в целях безопасности отключена возможность изменения прав доступа для исполняемых файлов;
В большинстве систем для нужд суперпользователя выделяется немного больше пространства, чем для обычного пользователя. Таким способом создается минимально необходимый резерв на случай отсутствия свободного места в файловой системе.