Чтение онлайн

ЖАНРЫ

Шрифт:

Более старые версии 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

> user 121

PER PROCESS USER AREA FOR PROCESS 121

PROCESS MISC:

 command: bash, psargs: -bash

 start: PO Mon 24 18:11:31 1997

 mem: 1ebc, type: exec

 vnode of current directory: f5b95e40

OPEN FILES, POFILE FLAGS, AND THREAD REFCNT:

[0] : F 0xf62b6030, 0, 0 [1] : F 0xf62b6030, 0, 0

[2] : F 0xf62b6030, 0, 0

 cmask: 0022

RESOURCE LIMITS:

 cpu time: unlimited/unlimited

 file size: unlimited/unlimited

 swap size: 2147479552/2147479552

 stack size: 8388608/2147479552

 coredump size: unlimited/unlimited

 file descriptors: 64/1024

 address space: unlimited/unlimited

SIGNAL DISPOSITION:

...

Файловая таблица

Поля файлового дескриптора

u_ofile
и u_
pofile
содержат начальную информацию, необходимую для доступа процесса к данным файла. Дополнительная информация находится в системной файловой таблице и таблице индексных дескрипторов. Для обеспечения доступа процесса к данным файла ядро должно полностью создать цепочку от файлового дескриптора до vnode и, соответственно, до блоков хранения данных, как показано на рис. 4.12.

Каждый элемент файловой таблицы содержит информацию, необходимую для управления работой с файлом. Если несколько процессов открывают один и тот же файл, каждый из них получает собственный элемент файловой таблицы, хотя все они будут работать с одним и тем же файлом. Важнейшие поля элемента файловой таблицы приведены ниже:

Поле Описание
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 исследуем его содержимое:

> file 0xf62b6030

ADDRESS RCNT TYPE/ADDR OFFSET FLAGS

f62b6030 9 SPEC/f5e91c1c 15834 read write

> vnode f5e91c1c

VCNT VFSMNTED VFSP STREAMP VTYPE RDEV VDATA VFILOCKS VFLAG

2 0 f0286570 f5c6b2a0 c 24,26 f5e91c18 0 -

Поскольку это специальный файл устройства (об этом свидетельствует поле TYPE элемента файловой таблицы), поле

v_data
(
VDATA
) vnode указывает не на inode файловой системы ufs, а на snode — индексный дескриптор логической файловой системы specfs, обслуживающей специальные файлы устройств. Более подробно этот интерфейс будет рассматриваться в следующей главе. Таким образом, для продолжения путешествия по структурам данных ядра, следует обратиться к snode, адрес которого указан в поле
VDATA
.

> snode f5e91c18

SNODE TABLE SIZE = 256

HASH-SLOT MAJ/MIN REALVP COMMONVP NEXTR SIZE COUNT FLAGS

– 24,26 f5f992e8 f636b27c 0 0 0 up ас

Поле

s_realvp
(
REALVP
) указывает на vnode файла реальной файловой системы (в данном случае ufs). Поэтому далее поиск аналогичен проделанному при исследовании таблицы монтирования.

> vnode f5f992e8

VCNT VFSMNTED VFSP STREAMP VTYPE RDEV VDATA VFILOCKS VFLAG

2 0 f0286570 0 с 24,26 f5f992e0 0 -

> ui f5f992e0

 UFS INODE TABLE SIZE = 1671

SLOT MAJ/MIN INUMB RCNT LINE UID GID SIZE MODE FLAGS

– 32,24 317329 2 1 286 7 0 c---620 rf

> ! ncheck.
– i 317329

/dev/dsk/c0t3d0s0:

317329 /devices/pseudo/pts@0:26

В результате мы определили имя специального файла устройства (в данном случае — это псевдотерминал), на которое производится ввод и вывод командного интерпретатора.

Блокирование доступа к файлу

Традиционно архитектура файловой подсистемы UNIX разрешает нескольким процессам одновременный доступ к файлу для чтения и записи. Хотя операции записи и чтения, осуществляемые с помощью системных вызовов read(2) или write(2), являются атомарными, в UNIX по умолчанию отсутствует синхронизация между отдельными вызовами. Другими словами, между двумя последовательными вызовами read(2) одного процесса другой процесс может модифицировать данные файла. Это, в частности, может привести к несогласованным операциям с файлом, и как следствие, к нарушению целостности его данных. Такая ситуация является неприемлемой для многих приложений.

Поделиться с друзьями: