Операционная система UNIX - Робачевский Андрей Михайлович
Шрифт:
Интервал:
Закладка:
Говоря формально, полное имя файла представляет собой последовательность слов, разделенных символом '/'. Каждый компонент имени, кроме последнего, является именем каталога. Последний компонент определяет собственно имя файла. При этом полное имя может быть абсолютным или относительным. Если полное имя начинается с символа '/', представляющего корневой каталог общего логического дерева файловой системы, то оно является абсолютным, однозначно определяющим файл из любого места файловой системы. В противном случае, имя является относительным и адресует файл относительно текущего каталога. Примером относительного имени может служить include/sys/user.h, а абсолютное имя этого файла — /usr/include/sys/user.h. Как следует из этих рассуждений, два каталога играют ключевую роль при трансляции имени: корневой каталог и текущий каталог. Каждый процесс адресует эти каталоги двумя полями структуры u_area:
struct vnode *u_cdir Указатель на vnode текущего каталога struct vnode *u_rdir Указатель на vnode корневого каталогаВ зависимости от имени файла трансляция начинается с vnode, адресованного либо полем u_cdir, либо u_rdir. Трансляция имени осуществляется покомпонентно, при этом для vnode текущего каталога вызывается соответствующая ему операция vn_lookup(), в качестве аргумента которой передается имя следующего компонента. В результате операции возвращается vnode, соответствующий искомому компоненту.
Если для vnode каталога установлен указатель vn_vfsmountedhere, то данный каталог является точкой монтирования. Если имя файла требует дальнейшего спуска по дереву файловой системы (т.е. пересечения точки монтирования), то операция vn_lookup() следует указателю vn_vfsmountedhere для перехода в подключенную файловую систему и вызывает для нее операцию vfs_root для получения ее корневого vnode. Трансляция имени затем продолжается с этого места.
Пересечение границы файловых систем возможно и при восхождении по дереву, например, если имя файла задано указанием родительского каталога — ../../myfile.txt. Если при движении в этом направлении по пути встречается корневой vnode подключенной файловой системы (установлен флаг VROOT в поле v_flag), то операция vn_lookup() следует указателю vfs_vnodecovered, расположенному в записи vfs этой файловой системы. При этом происходит пересечение границы файловых систем, и дальнейшая трансляция продолжается с точки монтирования.
Если искомый файл является символической связью, и системный вызов, от имени которого происходит трансляция имени, "следует" символической связи, операция vn_lookup() вызывает vn_readlink() для получения имени целевого файла. Если оно является абсолютным (т.е. начинается с "/"), то трансляция начинается с vnode корневого каталога, адресованного полем u_rdir области u-area.
Процесс трансляции имени продолжается, пока не просмотрены все компоненты имени или не обнаружена ошибка (например, отсутствие прав доступа). В случае удачного завершения возвращается vnode искомого файла.
Доступ к файловой системе
Как было показано в главе 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.