Шрифт:
Файловая таблица
Поля файлового дескриптора
Каждый элемент файловой таблицы содержит информацию, необходимую для управления работой с файлом. Если несколько процессов открывают один и тот же файл, каждый из них получает собственный элемент файловой таблицы, хотя все они будут работать с одним и тем же файлом. Важнейшие поля элемента файловой таблицы приведены ниже:
Поле | Описание |
---|---|
f_flag | Флаги, указанные при открытии файла (системные вызовы open(2), creat(2)). Каждая операция с файлом проверяется на допустимость согласно указанным режимам. Другими словами, если процесс открыл файл только для чтения (флаг FREAD ), ему будет отказано в операции записи, даже если он имеет на это необходимые права доступа. |
FREAD | Файл открыт только для чтения. То же, что и O_RDONLY при открытии файла. |
FWRITE | Файл открыт только на запись. То же, что и O_WRONLY при открытии файла. |
FAPPEND | Режим добавления. Перед началом операции записи файловый указатель будет установлен в конец файла. То же, что и O_APPEND при открытии файла. |
FNONBLOCK , FNDELAY | Возврат без блокирования. Системный вызов не будет ожидать завершения операции. То же, что и O_NONBLOCK или O_NDELAY при открытии файла. |
FSYNC | Обеспечить синхронизацию с соответствующими дисковыми структурами для метаданных и данных файла при совершении операции записи. То же, что и O_SYNC при открытии файла. |
FDSYNC | Обеспечить синхронизацию с соответствующими дисковыми структурами только для данных файла при совершении операции записи. То же, что и O_DSYNC при открытии файла. |
FRSYNC | Совместно с флагами FSYNC и FDSYNC определяет процесс синхронизации для соответствующих компонентов файла при операции чтения. |
f_count | Число файловых дескрипторов, адресующих данный элемент файловой таблицы. Один и тот же элемент файловой таблицы может совместно использоваться при дублировании дескрипторов с помощью системного вызова dup(2) или в результате fork(2). |
f_vnode | Указатель на виртуальный индексный дескриптор файла. |
f_offset | Текущее смещение в файле. Начиная с этого места будет произведена следующая операция чтения или записи. |
Для иллюстрации обсуждения продолжим работу с утилитой crash(1M). С помощью команды user в предыдущем разделе были получены адреса элементов файловой таблицы для стандартного ввода (fd=0), вывода (fd=1) и вывода сообщений об ошибках (fd=2). Заметим, что все они указывают на один и тот же элемент. С помощью команды file исследуем его содержимое:
Поскольку это специальный файл устройства (об этом свидетельствует поле TYPE элемента файловой таблицы), поле
Поле
– i 317329
В результате мы определили имя специального файла устройства (в данном случае — это псевдотерминал), на которое производится ввод и вывод командного интерпретатора.
Блокирование доступа к файлу
Традиционно архитектура файловой подсистемы UNIX разрешает нескольким процессам одновременный доступ к файлу для чтения и записи. Хотя операции записи и чтения, осуществляемые с помощью системных вызовов read(2) или write(2), являются атомарными, в UNIX по умолчанию отсутствует синхронизация между отдельными вызовами. Другими словами, между двумя последовательными вызовами read(2) одного процесса другой процесс может модифицировать данные файла. Это, в частности, может привести к несогласованным операциям с файлом, и как следствие, к нарушению целостности его данных. Такая ситуация является неприемлемой для многих приложений.
UNIX позволяет обеспечить блокирование заданного диапазона байтов файла или записи файла. Для этого служат базовый системный вызов управления файлом fcntl(2) и библиотечная функция lockf(3C), предназначенная специально для управления блокированием. При этом перед фактической файловой операцией (чтения или записи) процесс устанавливает блокирование соответствующего типа (для чтения или для записи). Если блокирование завершилось успешно, это означает, что требуемая файловая операция не создаст конфликта или нарушения целостности данных, например, при одновременной записи в файл несколькими процессами.