Системные операции для работы с файловой системой.

16/04/96 13:25 u_f-work.lek
Морис Дж. Бах (Maurice J. Bach) "THE DESIGN OF THE UNIX OPERATING SYSTEM" Copyright c 1986 Корпорация Bell Telephone Laboratories. Перевод с английского к.т.н. Крюкова А.В.

Системные операции для работы с файловой системой.

Рассматриваются системные функции, обеспечивающие обращение к существующим файлам, такие как open, read, write, lseek и close; функции создания новых файлов, а именно, creat и mknod; функции для работы с индексом или для передвижения по файловой системе: chdir, chroot, chown, stat и fstat.

Исследуются более сложные системные функции: pipe и dup имеют важное значение для реализации каналов в shell'е; mount и umount расширяют видимое для пользователя дерево файловых систем; link и unlink изменяют иерархическую структуру файловой системы.

Функции для работы с файловой системой

Рисунок. Функции для работы с файловой системой и их связь с другими алгоритмами

Системные функции классифицируются на несколько категорий, хотя некоторые из функций присутствуют более, чем в одной категории:

OPEN

Вызов системной функции open (открыть файл) - это первый шаг, который должен сделать процесс, чтобы обратиться к данным в файле. Синтаксис вызова функции open:

fd = open(pathname,flags,modes);

где:

Системная функция open возвращает целое число (или -1 при ошибке), именуемое ПОЛЮЗОВАТЕЛЬСКИМ ДЕСКРИПТОРОМ ФАЙЛА. Другие операции над файлами, используют значение дескриптора файла, возвращаемое системной функцией open.

Ядро просматривает файловую систему в поисках файла по его имени, используя алгоритм namei. Оно проверяет права на открытие файла после того, как обнаружит копию индекса файла в памяти, и выделяет открываемому файлу запись в таблице файлов.

Запись таблицы файлов содержит указатель на индекс открытого файла и поле, в котором хранится смещение в байтах от начала файла до места, откуда предполагается начинать выполнение последующих операций чтения или записи.

Ядро выделяет запись в личной (закрытой) таблице в адресном пространстве задачи, выделенном процессу (таблице пользовательских дескрипторов файлов), и запоминает указатель на эту запись. Указателем выступает дескриптор файла, возвращаемый пользователю. Запись в таблице пользовательских файлов указывает на запись в глобальной таблице файлов.

Процесс A:

fd1 = open("/etc/passwd",O_RDONLY);

fd2 = open("local",O_RDWR);

fd3 = open("/etc/passwd",O_WRONLY);

Процесс B:

fd1 = open("/etc/passwd",O_RDONLY);

fd2 = open("private",O_RDONLY);

ПРИМЕЧАНИЕ:
1. В описании вызова системной функции open содержатся три параметра, но третий нужен только при открытии несуществующего файла.
2. Первые три пользовательских дескриптора (0, 1 и 2) обычно резервируются под дескрипторы файлов:
- стандартного ввода,
- стандартного вывода,
- стандартного файла ошибок.
В операционной системе нет никакого указания на то, что эти дескрипторы файлов являются специальными.

 

таблицы пользовательских дескрипторов файла

Рисунок. Структуры данных после того, как два процесса произвели открытие файлов

READ

Синтаксис вызова системной функции read (читать):

number = read(fd,buffer,count)

где:

Алгоритм:

- Ядро обращается в таблице файлов к записи, которая соответствует значению пользовательского дескриптора файла, следуя за указателем.

- Затем оно устанавливает значения нескольких параметров ввода-вывода в адресном пространстве процесса:

- Далее ядро обращается к индексу, используя указатель из таблицы файлов, и блокирует его прежде, чем начать чтение из файла.

- Затем в алгоритме начинается цикл, выполняющийся до тех пор, пока операция чтения не будет произведена до конца:

Ядро преобразует смещение в байтах внутри файла в номер блока, используя алгоритм bmap, и вычисляет смещение внутри блока до места, откуда следует начать ввод-вывод, а также количество байт, которые будут прочитаны из блока. После считывания блока в буфер ядро копирует данные из блока по назначенному адресу в пользовательском процессе. Оно корректирует параметры ввода-вывода в адресном пространстве процесса в соответствии с количеством прочитанных байт. Если запрос пользователя не удовлетворен, ядро повторяет весь цикл. Цикл завершается, либо когда ядро выполнит запрос пользователя полностью, либо когда в файле больше не будет данных, либо если ядро обнаружит ошибку при чтении данных с диска или при копировании данных в пространство пользователя.

- После полного завершения операции индекс деблокируется и возвращается количество прочитанных байт.

WRITE

Синтаксис вызова системной функции write (писать):

number = write(fd,buffer,count);

где переменные fd, buffer, count и number имеют тот же смысл, что и для вызова системной функции read.

Алгоритм записи в обычный файл похож на алгоритм чтения из обычного файла. Однако, если в файле отсутствует блок, соответствующий смещению в байтах до места, куда должна производиться запись, ядро выделяет блок, используя алгоритм alloc, и присваивает ему номер в соответствии с точным указанием места в таблице содержимого индекса. Если смещение в байтах совпадает со смещением для блока косвенной адресации, ядру, возможно, придется выделить несколько блоков для использования их в качестве блоков косвенной адресации и информационных блоков.

Индекс блокируется на все время выполнения функции write, так как ядро может изменить индекс, выделяя новые блоки; разрешение другим процессам обращаться к файлу может разрушить индекс, если несколько процессов выделяют блоки одновременно, используя одни и те же значения смещений. Когда запись завершается, ядро корректирует размер файла в индексе, если файл увеличился в размере.

FCNTL

В первой версии системы UNIX, отсутствовал внутренний механизм, с помощью которого процессу мог бы быть обеспечен исключительный доступ к файлу.

Для того, чтобы повысить привлекательность системы UNIX для коммерческих пользователей, работающих с базами данных, в версию V системы включены механизмы захвата файла и записи.

ЗАХВАТ ФАЙЛА - это средство, позволяющее запретить другим процессам производить чтение или запись любой части файла, а ЗАХВАТ ЗАПИСИ - это средство, позволяющее запретить другим процессам производить ввод-вывод указанных частей файла между некоторыми смещениями.

Функция fcntl используется для реализации механизма захвата файла и записи и имеет следующий формат:

fcntl(fd,cmd,arg);

где:

* Проверка наличия блокировок, принадлежащих другим процессам, с немедленным возвратом управления в случае обнаружения таких блокировок,

* Установка блокировки и приостанов до успешного завершения,

* Установка блокировки с немедленным возвратом управления в случае неудачи.

arg - указываются параметры: тип блокировки (записи или чтения) и смещения в байтах.

Ядро автоматически снимает блокировки, установленные процессом, при закрытии файла.

LSEEK

Обычное использование системных функций read и write обеспечивает последовательный доступ к файлу, однако процессы могут использовать вызов системной функции lseek для указания места в файле, где будет производиться ввод-вывод, и осуществления произвольного доступа к файлу.

Синтаксис вызова системной функции:

position = lseek(fd,offset,reference);

где:

CLOSE

Процесс закрывает открытый файл, когда процессу больше не нужно обращаться к нему. Синтаксис вызова системной функции close (закрыть):

close(fd);

где fd - дескриптор открытого файла.

Ядро выполняет операцию закрытия, используя дескриптор файла и информацию из соответствующих записей в таблице файлов и таблице индексов. Если счетчик ссылок в записи таблицы файлов имеет значение, большее, чем 1, в связи с тем, что были обращения к функциям dup или fork, то это означает, что на запись в таблице файлов делают ссылку другие пользовательские дескрипторы; ядро уменьшает значение счетчика и операция закрытия завершается.

Если счетчик ссылок в таблице файлов имеет значение, равное 1, ядро освобождает запись в таблице и индекс в памяти, ранее выделенный системной функцией open. Если другие процессы все еще ссылаются на индекс, ядро уменьшает значение счетчика ссылок на индекс, но оставляет индекс процессам; в противном случае индекс освобождается для переназначения, так как его счетчик ссылок содержит 0.

Когда выполнение системной функции close завершается, запись в таблице пользовательских дескрипторов файла становится пустой. Попытки процесса использовать данный дескриптор заканчиваются ошибкой. Когда процесс завершается, ядро проверяет наличие активных пользовательских дескрипторов файла, принадлежавших процессу, и закрывает каждый из них. Таким образом, ни один процесс не может оставить файл открытым после своего завершения.

CREATE

Системная функция open дает процессу доступ к существующему файлу, а системная функция creat создает в системе новый файл. Синтаксис вызова системной функции creat:

fd = creat(pathname,modes);

где переменные pathname, modes и fd имеют тот же смысл, что и в системной функции open. Если прежде такого файла не существовало, ядро создает новый файл с указанным именем и указанными правами доступа к нему; если же такой файл уже существовал, ядро усекает файл (освобождает все существующие блоки данных и устанавливает размер файла равным 0.

ПРИМЕЧАНИЕ: Системная функция open может отккрывать несуществующие файлы, для этого предусмотрено два флага, O_CREAT (создание) и O_TRUNC (усечение). Если процесс устанавливает в вызове функции флаг O_CREAT и файл не существует, ядро создаст файл. Если файл уже существует, он не будет усечен, если только не установлен флаг

O_TRUNC.

Ядро проводит синтаксический анализ имени пути поиска, используя алгоритм namei и следуя этому алгоритму буквально, когда речь идет о разборе имен каталогов. Однако, когда дело касается идентификатора создаваемого файла, namei отмечает смещение в байтах до первой пустой позиции в каталоге и запоминает это смещение в пространстве процесса. Если ядро не обнаружило в каталоге компоненту имени пути поиска (файл действительно новый), оно в конечном счете впишет имя компоненты в только что найденную пустую позицию.

Если в каталоге нет пустых позиций, ядро запоминает смещение до конца каталога и создает новую позицию там.

Ядро проверяет наличие у процесса разрешения на запись в каталог, означающее, что процессам дозволяется создавать файлы в каталоге.

Если в процессе анализа пути поиска выясняется, что файл уже существует, то проверяется наличие разрешения процессу производить запись в него, чтобы можно было создать "новый" файл с тем же самым именем, так как ядро изменяет содержимое файла при выполнении функции creat. При этом владелец и права доступа к файлу остаются прежними и не проверяет наличие разрешения на запись в каталог, являющийся родительским для существующего файла.

MKNOD

Системная функция mknod создает в системе специальные файлы, в число которых включаются поименованные каналы, файлы устройств и каталоги. Она похожа на функцию creat в том, что ядро выделяет для файла индекс.

Синтаксис вызова системной функции mknod:

mknod(pathname,type and permissions,dev)

где:

Ядро просматривает файловую систему в поисках имени файла, который оно собирается создать. Если файл еще пока не существует, ядро назначает ему новый индекс на диске и записывает имя нового файла и номер индекса в родительский каталог. Оно устанавливает значение поля типа файла в индексе, указывая, что файл является каналом, каталогом или специальным файлом.

Наконец, если файл является специальным файлом устройства блочного или символьного типа, ядро записывает в индекс старший и младший номера устройства.

Если функция mknod создает каталог, он будет существовать по завершении выполне ния функции, но его содержимое будет иметь неверный формат (в каталоге будут отсутствовать записи с именами "." и ".."). Эти записи создаются командой mkdir (создать новый каталог).

CHDIR

Когда система загружается впервые, нулевой процесс делает корневой каталог файловой системы текущим на время инициализации. Для индекса корневого каталога нулевой процесс выполняет алгоритм iget, сохраняет этот индекс в пространстве процесса в качестве индекса текущего каталога и снимает с индекса блокировку. Когда с помощью функции fork создается новый процесс, он наследует текущий каталог старого процесса в своем адресном пространстве, а ядро, соответственно, увеличивает значение счетчика ссылок в индексе.
Алгоритм chdir изменяет имя текущего каталога для процесса.

Синтаксис вызова системной функции chdir:

chdir(pathname);

где pathname - каталог, который становится текущим для процесса.

Ядро анализирует имя каталога, используя алгоритм namei, и проверяет, является ли данный файл каталогом и имеет ли владелец процесса право доступа к каталогу.

Ядро снимает с нового индекса блокировку, но удерживает индекс в качестве выделенного и оставляет счетчик ссылок без изменений, освобождает индекс прежнего текущего каталога (алгоритм iput), хранящийся в пространстве процесса, и запоминает в этом пространстве новый индекс. После смены процессом текущего каталога алгоритм namei использует индекс в качестве начального каталога при анализе всех имен путей, которые не берут начало от корня. Поокончании выполнения системной функции chdir счетчик ссылок на индекс нового каталога имеет значение, как минимум, 1, а счетчик ссылок на индекс прежнего текущего каталога может стать равным 0. Индекс, выделенный во время выполнения функции chdir, освобождается только тогда, когда процесс меняет текущий каталог еще раз или когда процесс завершается.

CHROOT

Процессы используют глобальный корневой каталог файловой системы для всех имен путей поиска, начинающихся с "/". Ядро хранит глобальную переменную, которая указывает на индекс глобального корня, выделяемый по алгоритму iget при загрузке системы. Процессы могут менять свое представление о корневом каталоге файловой системы с помощью системной функции chroot. Синтаксис вызова функции:

chroot(pathname);

где pathname - каталог, который впоследствии будет рассматриваться ядром в качестве корневого каталога для процесса.

Выполняя функцию chroot, ядро следует тому же алгоритму, что и при смене текущего каталога.

CHOWN, CHMOD

Смена владельца или режима (прав) доступа к файлу является операцией, производимой над индексом, а не над файлом. Синтаксис вызова соответствующих системных функций:

где:

Для того, чтобы поменять владельца файла, ядро преобразует имя файла в идентификатор индекса, используя алгоритм namei. Владелец процесса должен быть суперпользователем или владельцем файла. Затем ядро назначает файлу нового владельца и нового группового пользователя, сбрасывает флаги прежних установок и освобождает индекс по алгоритму iput.
Для того, чтобы поменять режим доступа к файлу, ядро выполняет процедуру, подобную описанной, меняя флаги, устанавливающие режим доступа.

STAT И FSTAT

Системные функции stat и fstat позволяют процессам запрашивать информацию о статусе файла: типе файла, владельце файла, правах доступа, размере файла, числе связей, номере индекса и времени доступа к файлу.

Синтаксис вызова функций:

где:

Системные функции просто переписывают поля из индекса в структуру

statbuffer:

struct stat {

dev_t st_dev; /* номер устройства, на котором находится файл */

ino_t st_ino; /* номер индекса */

ushort st_mode; /* тип файла (см. mknod) и права доступа к нему (см. chmod) */

short st_nlink; /* число связей, указывающих на файл */

ushort st_uid; /* код идентификации владельца файла */

ushort st_gid; /* код идентификации группы */

dev_t st_rdev; /* старший и младший номера устройства */

off_t st_size; /* размер в байтах */

time_t st_atime; /* время последнего обращения */

time_t st_mtime; /* время последнего внесения изменений */

time_t st_ctime; /* время последнего изменения статуса */

};

КАНАЛЫ

Каналы позволяют передавать данные между процессами в порядке поступления ("первым пришел - первым вышел"), а также синхронизировать выполнение процессов. Их использование дает процессам возможность взаимодействовать между собой, пусть даже не известно, какие процессы находятся на другом конце канала. Традиционная реализация каналов использует файловую систему для хранения данных.

Различают ДВА ВИДА КАНАЛОВ: ПОИМЕНОВАННЫЕ каналы и НЕПОИМЕНОВАННЫЕ каналы, которые идентичны между собой во всем, кроме способа первоначального обращения к ним процессов. Для поименованных каналов процессы используют системную функцию open, а системную функцию pipe - для создания непоименованного канала. Впоследствии, при работе с каналами процессы пользуются обычными системными функциями для файлов, такими как read, write и close. Только связанные между собой процессы, являющиеся потомками того процесса, который вызвал функцию pipe, могут разделять доступ к непоименованным каналам.

PIPE

Синтаксис вызова функции создания канала:

pipe(fdptr);

где fdptr - указатель на массив из двух целых переменных, в котором будут храниться два дескриптора файла для чтения из канала и для записи в канал.

Ядро назначает индекс для канала из файловой системы, обозначенной как "устройство канала", используя алгоритм ialloc. Устройство канала - это та файловая система, из которой ядро может назначать каналам индексы и выделять блоки для данных. Администраторы системы указывают устройство канала при конфигурировании системы и эти устройства могут совпадать у разных файловых систем. Пока канал активен, ядро не может переназначить индекс канала и информационные блоки канала другому файлу.

Затем ядро выделяет в таблице файлов две записи, соответствующие дескрипторам для чтения и записи в канал, и корректирует информацию в копии индекса в памяти. В каждой из выделенных записей в таблице файлов хранится информация о том, сколько экземпляров канала открыто для чтения или записи (первоначально 1), а счетчик ссылок в индексе указывает, сколько раз канал был "открыт" (первоначально 2 - по одному для каждой записи таблицы файлов).

Наконец, в индексе записываются смещения в байтах внутри канала до места, где будет начинаться следующая операция записи или чтения (для обычных файлов смещения хранятся в таблице файлов). Процессы не могут менять эти смещения с помощью системной функции lseek.

Открытие поименованного канала

Поименованный канал - это файл, имеющий почти такую же семантику, как и непоименованный канал, за исключением того, что этому файлу соответствует запись в каталоге и обращение к нему производится по имени. Процессы открывают поименованные каналы так же, как и обычные файлы.

Поименованные каналы постоянно присутствуют в иерархии файловой системы (из которой они удаляются с помощью системной функции unlink), а непоименованные каналы являются временными: когда все процессы заканчивают работу с каналом, ядро отбирает назад его индекс.
При использовании поименованных каналов должны существовать процессы пишущие и читающие информацию.

Если процесс открывает поименованный канал для чтения, причем процесс, записывающий в канал, существует, открытие завершается. Или если процесс открывает поименованный файл с параметром "no delay", функция open возвращает управление немедленно, даже когда нет ни одного записывающего процесса. Во всех остальных случаях процесс приостанавливается до тех пор, пока записывающий процесс не откроет канал.

Аналогичные правила действуют для процесса, открывающего канал для записи.

Чтение из каналов и запись в каналы

Можно считать, что процессы ведут запись на одном конце канала, а считывают данные на другом конце. Совпадение количества процессов, считывающих данные из канала, с количеством процессов, ведущих запись в канал, совсем не обязательно; если одно число отличается от другого более, чем на 1, процессы должны координировать свои действия по использованию канала с помощью других механизмов. Ядро обращается к данным в канале точно так же, как и к данным в обычном файле. Различие в выделении памяти для канала и для обычного файла состоит в том, что канал использует только блоки прямой адресации в целях повышения эффективности работы.

Ядро работает с блоками прямой адресации индекса как с циклической очередью, поддерживая в своей структуре указатели чтения и записи для обес печения очередности обслуживания "первым пришел - первым вышел".

 

Блоки прямой адресации в индексе

Рисунок. Логическая схема чтения и записи в канал

При выполненнии операций ввода-вывода в канал возможны следующие ситуации:

При отработке первых двух ситуаций проблем не возникает.

При возникновении двух последних, процессы приостанавлиают свое выполненния в ожидании выполненния процессов, осуществляющих обратную операцию (операция чтения возвратит только имеющиеся данные и остановится при попытке читать из пустого канала).

Закрытие каналов

При закрытии канала процесс выполняет ту же самую процедуру, что и при закрытии обычного файла, за исключением того, что ядро, прежде чем освободить индекс канала, выполняет специальную обработку. Оно уменьшает количество процессов чтения из канала или записи в канал в зависимости от типа файлового дескриптора. Если значение счетчика числа записывающих в канал процессов становится равным 0 и имеются процессы, приостановленные в ожидании чтения данных из канала, ядро возобновляет выполнение последних и они завершают свои операции чтения без возврата каких-либо данных.

Если становится равным 0 значение счетчика числа считывающих из канала процессов и имеются процессы, приостановленные в ожидании возможности записи данных в канал, ядро возобновляет выполнение последних и посылает им сигнал об ошибке. Ядро освобождает все информационные блоки канала и переустанавливает индекс таким образом, чтобы он указывал на то, что канал пуст. Когда ядро освобождает индекс обычного канала, оно освобождает для переназначения и дисковую копию этого индекса.

Примеры использования каналов.

Первая программа иллюстрирует искусственное использование непоименованного канала.
Процесс создает канал и входит в бесконечный цикл, записывая в канал строку символов "hello" и считывая ее из канала.

Процесс, выполняющий вторую программу создает поименованный канал с именем "fifo". Если этот процесс запущен с указанием формального аргумента, он постоянно записывает в канал строку символов "hello"; будучи запущен без аргумента, он ведет чтение из поименованного канала.

Рисунок. Чтение из канала и запись в непоименованный канал

 

Рисунок. Чтение и запись в поименованный канал

DUP

Системная функция dup копирует дескриптор файла в первое свободное место в таблице пользовательских дескрипторов файла, возвращая новый дескриптор пользователю. Она действует для всех типов файла. Синтаксис вызова функции:

newfd = dup(fd);

где:

Поскольку функция dup дублирует дескриптор файла, она увеличивает значение счетчика в соответствующей записи таблицы файлов - записи, на которую указывают связанные с ней точки входа в таблице файловых дескрипторов, которых теперь стало на одну больше.

Рисунок. Структуры данных после выполнения:

fd3 = open("/etc/passwd",O_RDONLY);

fd4 = open("local",O_RDWR);

fd5 = open("/etc/passwd",O_WRONLY);

fd6 = dup(fd3);

Использование копирования дескрипторов отличается от нового открытия файла с тем же именем тем, что обращение к файлу осуществляется с использованием одного и того же указателя смещения из таблицы файлов.

МОНТИРОВАНИЕ И ДЕМОНТИРОВАНИЕ ФАЙЛОВЫХ СИСТЕМ

Физический диск состоит из нескольких логических разделов, на которые он разбит дисковым драйвером, причем каждому разделу соответствует файл устройства, имеющий определенное имя. Процессы обращаются к данным раздела, открывая соответствующий файл устройства и затем ведя запись и чтение из этого "файла", представляя его себе в виде последовательности дисковых блоков. Раздел диска может содержать логическую файловую систему, состоящую из блока начальной загрузки, суперблока, списка индексов и информационных блоков.

Системная функция mount (монтировать) связывает файловую систему из указанного раздела на диске с существующей иерархией файловых систем, а функция umount (демонтировать) выключает файловую систему из иерархии.

Функция mount, таким образом, дает пользователям возможность обращаться к данным в дисковом разделе как к файловой системе, а не как к последовательности дисковых блоков.

Синтаксис вызова функции mount:

mount(special pathname,directory pathname,options);

где:

Рисунок. Дерево файловых систем до и после выполнения функции mount("/dev/dsk1","/usr",0);

Файл "/dev/dsk1" является блочным специальным файлом, т.е. он носит имя устройства блочного типа, обычно имя раздела на диске.
Ядро поддерживает таблицу монтирования с записями о каждой монтированной файловой системе. В каждой записи таблицы монтирования содержатся:

Связь индекса точки монтирования с корневым индексом монтированной файловой системы, возникшая в результате выполнения системной функции mount, дает ядру возможность легко двигаться по иерархии файловых систем без получения от пользователей дополнительных сведений.

Ядро позволяет монтировать и демонтировать файловые системы только тем процессам, владельцем которых является суперпользователь.

Алгоритм монтирования:

Пересечение точек монтирования в маршрутах поиска имен файлов

cd /usr/src/uts

cd ../../..

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

Рисунок. Структуры данных после монтирования

Для второго случая пересечения точки монтирования в направлении из файловой системы, которая монтируется, в файловую систему, где выполняется монтирование после обнаружения в каталоге номера индекса для данной компоненты пути поиска ядро проверяет, не указывает ли номер индекса на то, что это корневой индекс файловой системы. Если это так и если текущий рабочий индекс так же является корневым, а компонента пути поиска, в свою очередь, имеет имя "..", ядро идентифицирует индекс как точку монтирования.

Оно находит в таблице монтирования запись, номер устройства в которой совпадает с номером устройства для последнего из найденных индексов, получает индекс для каталога, в котором производится монтирование, и продолжает поиск компоненты с именем "..", используя только что полученный индекс в качестве рабочего.

Демонтирование файловой системы

Синтаксис вызова системной функции umount:

umount(special filename);

где special filename указывает демонтируемую файловую систему.

Алгоритм демонтирования:

LINK

Системная функция link связывает файл с новым именем в структуре каталогов файловой системы, создавая для существующего индекса новую запись в каталоге.

Синтаксис вызова функции link:

link(source file name, target file name);

где:

Файловая система хранит имя пути поиска для каждой связи, имеющейся у файла, и процессы могут обращаться к файлу по любому из этих имен. Ядро не знает, какое из имен файла является его подлинным именем, поэтому имя файла специально не обрабатывается. Например, после выполнения набора функций

link("/usr/src/uts/sys","/usr/include/sys");

link("/usr/include/realfile.h","/usr/src/uts/sys/testfile.h");

на один и тот же файл будут указывать три имени пути поиска:

Рисунок. Файлы в дереве файловой системы, связанные с помощью функции link

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

Алгоритм выполнения связывания:

UNLINK

Системная функция unlink удаляет из каталога точку входа для файла. Синтаксис вызова функции unlink:

unlink(pathname);

где pathname указывает имя файла, удаляемое из иерархии каталогов.

Алгоритм:

АБСТРАКТНЫЕ ОБРАЩЕНИЯ К ФАЙЛОВЫМ СИСТЕМАМ

Существует понятие "тип файловой системы. Наличие типа файловой системы дает ядру возможность поддерживать одновременно множество файловых систем, таких как сетевые файловые системы или даже файловые системы из других операционных систем. Процессы пользуются для обращения к файлам обычными функциями системы UNIX, а ядро устанавливает соответствие между общим набором файловых операций и операциями, специфичными для каждого типа файловой системы.

 

Рисунок. Индексы для файловых систем различных типов

Индекс выступает интерфейсом между абстрактной файловой системой и отдельной файловой системой. Общая копия индекса в памяти содержит информацию, не зависящую от отдельной файловой системы, а также указатель на частный индекс файловой системы, который уже содержит информацию, специфичную для нее.
Предполагается, что последний индекс содержит достаточно информации для того, чтобы идентифицировать файл, находящийся в удаленной системе.У файловой системы может отсутствовать структура, подобная индексу; но исходный текст программ отдельной файловой системы должен позволять создать объектный код, удовлетворяющий семантическим требованиям файловой системы UNIX и назначающий свой "индекс", который соответствует общему индексу, назначаемому ядром.

Файловая система каждого типа имеет некую структуру, в которой хранятся адреса функций, реализующих абстрактные действия. Когда ядру нужно обратиться к файлу, оно вызывает косвенную функцию в зависимости от типа файловой системы и абстрактного действия.

СОПРОВОЖДЕНИЕ ФАЙЛОВОЙ СИСТЕМЫ

Ядро поддерживает целостность системы в своей обычной работе. Тем не менее, такие чрезвычайные обстоятельства, как отказ питания, могут привести к фатальному сбою системы, в результате которого содержимое системы утрачивает свою согласованность: большинство данных в файловой системе доступно для использования, но некоторая несогласованность между ними имеет место. Команда fsck проверяет согласованность данных и в случае необходимости вносит в файловую систему исправления. Она обращается к файловой системе через блочный или строковый интерфейс в обход традиционных методов доступа к файлам.

Некоторые возможные ситуации:

Также это может случиться, если процесс, удаляя связь файла с каталогом, запишет освободившийся индекс на диск, но не успеет откорректировать каталог из-за сбоя.


Stay-at-home