Доступ к файловой системе
Как было показано в главе 2, процесс совершает операции с файлами, адресуя их при помощи файловых дескрипторов — целых чисел, имеющих локальное для процесса значение. Это значит, что файловый дескриптор одного процесса может адресовать совершенно другой файл, нежели файловый дескриптор с таким же номером, используемый другим процессом. Процесс получает файловый дескриптор с помощью ряда системных вызовов, например, open(2) или creat(2) ), выполняющих операцию трансляции имени, в результате которой выделяемый файловый дескриптор адресует определенный (или vnode) и, соответственно, файл файловой системы.
На рис. 4.12 показаны основные структуры ядра, необходимые для доступа процесса к файлу.
Рис. 4.12. Внутренние структуры доступа к файлу
Файловый дескриптор, используемый для доступа процесса к файлу, является индексом таблицы файловых дескрипторов (file descriptor table). Каждый процесс имеет собственную таблицу файловых дескрипторов, которая расположена в его u-area. На рис. 4.12 показаны два процесса, каждый из которых использует собственную таблицу файловых дескрипторов.
Каждая активная запись этой таблицы, представляющая открытый файл, адресует запись системной файловой таблицы (system file table), в которой хранятся такие параметры, как режим доступа к файлу (запись, чтение, добавление и т.д.), текущее смещение в файле (файловый указатель), а также указатель па vnode этого файла. Системная файловая таблица одна и совместно используется всеми процессами.
Как следует из рис. 4.12, несколько записей системной файловой таблицы могут адресовать один и тот же файл, который представлен единственной записью в таблице vnode.
Файловый дескриптор представляет собой неотрицательное целое число, возвращаемое системными вызовами, такими как creat(2) , open(2) или pipe(2) . После получения файлового дескриптора процесс может использовать его для дальнейшей работы с файлом, например с помощью системных вызовов read(2) , write(2) , close(2) или fcntl(2) .
Ядро обеспечивает работу процесса с файлами, используя различные структуры данных, часть из которых расположена в u-area процесса. Напомним, что эта область описывается структурой user
. В табл. 4.7 приведены поля структуры user
, которые используются ядром для обеспечения доступа процесса к файлу.
Таблица 4.7. Поля структуры user, связанные с файловым дескриптором
Поле |
Описание |
u_ofile |
Указатель на системную файловую таблицу |
u_pofile |
Флаги файлового дескриптора |
Файловый дескриптор связан с этими двумя полями и, таким образом, обеспечивает доступ к соответствующему элементу файловой таблицы (структуре данных file
).
В настоящее время в качестве единственного флага файлового дескриптора определен флаг FD_CLOEXEC
. Если этот флаг установлен, то производится закрытие файлового дескриптора (аналогично явному вызову close(2) ) при выполнении процессом системного вызова exec(2) ). При этом для запущенной программы не происходит наследования файлового дескриптора и доступа к файлу.
Более старые версии UNIX используют статическую таблицу дескрипторов, которая целиком хранится в u-area. Номер дескриптора является индексом этой таблицы. Таким образом, размер таблицы, которая обычно содержит 64 элемента, накладывает ограничение на число одновременно открытых процессом файлов. В современных версиях таблица размещается динамически и может увеличиваться при необходимости. Следует, однако, иметь в виду, что и в этом случае максимальное число одновременно открытых файлов регламентируется пределом RLIMIT_NOFILE
, который рассматривался в разделе "Ограничения" главы 2. В некоторых версиях, например, Solaris 2.5, данные файловых дескрипторов хранятся не в виде таблицы, а в виде блоков структур uf_entry
, поля которой аналогичны приведенным в табл. 4.7.
Содержимое таблицы дескрипторов процесса можно посмотреть с помощью утилиты crash(1M) . Команда user покажет содержимое u-area процесса. Например, для текущего командного интерпретатора мы получим следующую информацию:
# crash
> proc #8591
PROC TABLE SIZE = 1498
SLOT ST PID PPID PGID SID UID PRI NAME FLAGS
121 s 8591 8589 8591 8591 286 48 bash load jctl
Читать дальше