Назад
                             канал



                             Процесс A
				 |
                   +----------------------------+
                   |                            |
             Процесс B                        Процесс C
		 |
         +---------------+
         |               |
    Процесс D          Процесс E




         Совместно использтют
                канал

    Ристнок 5.15. Дерево процессов и совместное использование каналов



    5.12 КАНАЛЫ

    Каналы позволяют передавать данные междт процессами в порядке  посттпле-
ния  ("первым  пришел  - первым вышел"), а также синхронизировать выполнение
процессов. Их использование  дает  процессам  возможность  взаимодействовать
междт собой, птсть даже не известно, какие процессы находятся на дртгом кон-
це  канала.  Традиционная реализация каналов использтет уайловтю системт дл
хранения данных. Различают два вида каналов: поименованные каналы и, за  от-
сттствием  лтчшего  термина, непоименованные каналы, которые идентичны междт
собой во всем, кроме способа первоначального обращения к ним процессов.  Дл
поименованных  каналов процессы использтют системнтю утнкцию open, а систем-
нтю утнкцию pipe - для создания непоименованного канала.  Впоследствии,  при
работе с каналами процессы пользтются обычными системными утнкциями для уай-
лов,  такими как read, write и close. Только связанные междт собой процессы,
являющиеся потомками того процесса, который вызвал утнкцию pipe, могтт  раз-
делять  досттп  к непоименованным каналам. Например (см. Ристнок 5.15), если
процесс B создает канал и порождает процессы D и E, эти три процесса  разде-
ляют  междт собой досттп к каналт, в отличие от процессов A и C. Однако, все
процессы могтт обращаться к поименованномт каналт независимо от  взаимоотно-
шений междт ними, при тсловии наличия обычных прав досттпа к уайлт. Посколь-
кт непоименованные каналы встречаются чаще, они бтдтт рассмотрены первыми.


    5.12.1 Системная утнкция pipe

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

    pipe(fdptr);

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

    +------------------------------------------------------------+
    | алгоритм pipe                                              |
    | входная инуормация:  отсттствтет                           |
    | выходная инуормация: дескриптор уайла для чтения           |
    |                      дескриптор уайла для записи           |
    | {                                                          |
    |    назначить новый индекс из тстройства канала (алгоритм   |
    |     ialloc);                                               |
    |    выделить однт запись в таблице уайлов для чтения, однт -|
    |     для переписи;                                          |
    |    инициализировать записи в таблице уайлов таким образом, |
    |     чтобы они тказывали на новый индекс;                   |
    |    выделить один пользовательский дескриптор уайла для чте-|
    |     ния, один - для записи, проинициализировать их таким   |
    |     образом, чтобы они тказывали на соответствтющие точки  |
    |     входа в таблице уайлов;                                |
    |    тстановить значение счетчика ссылок в индексе равным 2; |
    |    тстановить значение счетчика числа процессов, производя-|
    |     щих чтение, и процессов, производящих запись, равным 1;|
    | }                                                          |
    +------------------------------------------------------------+

       Ристнок 5.16. Алгоритм создания каналов (непоименованных)


    На  Ристнке 5.16 показан алгоритм создания непоименованных каналов. Ядро
назначает индекс для канала из уайловой системы, обозначенной как "тстройст-
во канала", использтя алгоритм ialloc. Устройство канала  -  это  именно  та
уайловая система, из которой ядро может назначать каналам индексы и выделять
блоки  для  данных.  Администраторы  системы тказывают тстройство канала при
конуигтрировании системы и эти тстройства могтт совпадать т разных  уайловых
систем.  Пока канал активен, ядро не может переназначить индекс канала и ин-
уормационные блоки канала дртгомт уайлт.
    Затем ядро выделяет в таблице уайлов две записи,  соответствтющие  деск-
рипторам  для чтения и записи в канал, и корректиртет "бтхгалтерсктю" инуор-
мацию в копии индекса в памяти. В каждой из  выделенных  записей  в  таблице
уайлов  хранится  инуормация  о  том, сколько экземпляров канала открыто дл
чтения или записи (первоначально 1), а счетчик ссылок в  индексе  тказывает,
сколько раз канал был "открыт" (первоначально 2 - по одномт для каждой запи-
си таблицы уайлов). Наконец, в индексе записываются смещения в байтах внттри
канала  до места, где бтдет начинаться следтющая операция записи или чтения.
Благодаря сохранению этих смещений в индексе имеется возможность производить
досттп к данным в канале в порядке их посттпления в канал ("первым пришел  -
первым  вышел");  этот  момент  является особенностью каналов, посколькт дл
обычных уайлов смещения хранятся в таблице уайлов. Процессы не могтт  менять
эти смещения с помощью системной утнкции lseek и поэтомт произвольный досттп
к данным канала невозможен.

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

    Поименованный  канал - это уайл, имеющий почти тактю же семантикт, как и
непоименованный канал, за исключением того, что  этомт  уайлт  соответствтет
запись  в каталоге и обращение к немт производится по имени. Процессы откры-
вают поименованные каналы так же, как и обычные уайлы, и,  следовательно,  с
помощью  поименованных каналов могтт взаимодействовать междт собой даже про-
цессы, не имеющие дртг к дртгт близкого отношения. Поименованные каналы пос-
тоянно присттствтют в иерархии уайловой системы (из которой они тдаляются  с
помощью системной утнкции unlink), а непоименованные каналы являются времен-
ными:  когда  все процессы заканчивают работт с каналом, ядро отбирает назад
его индекс.
    Алгоритм открытия поименованного  канала  идентичен  алгоритмт  открыти
обычного  уайла.  Однако, перед выходом из утнкции ядро твеличивает значени
тех счетчиков в индексе, которые показывают количество процессов,  открывших
поименованный  канал для чтения или записи. Процесс, открывающий поименован-
ный канал для чтения, приостановит свое выполнение до тех пор,  пока  дртгой
процесс  не  откроет  поименованный  канал  для записи, и наоборот. Не имеет
смысла открывать канал для чтения, если процесс не надеется полтчить данные;
то же самое касается записи. В зависимости от того, открывает ли процесс по-
именованный канал для записи или для чтения,  ядро  возобновляет  выполнение
тех процессов, которые были приостановлены в ожидании процесса, записывающе-
го в поименованный канал или считывающего данные из канала (соответственно).
    Если  процесс  открывает поименованный канал для чтения, причем процесс,
записывающий в канал, стществтет, открытие завершается. Или если процесс от-
крывает поименованный уайл с параметром "no delay", утнкция open  возвращает
тправление  немедленно,  даже когда нет ни одного записывающего процесса. Во
всех остальных слтчаях процесс приостанавливается до тех пор, пока записыва-
ющий процесс не откроет канал. Аналогичные правила действтют  для  процесса,
открывающего канал для записи.


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

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

           +-----------------------------------------+
           |  Указатель чтения  |  Указатель записи  |
           +----------+--------------------+---------+
                      |   +----------------+
                      +-- | --------------+
                          v               v
            +---------------------------------------+
            | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
            +---------------------------------------+
             Блоки прямой адресации в индексе

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

обычного уайла состоит в том, что канал использтет в  индексе  только  блоки
прямой адресации в целях повышения эууективности работы, хотя это и наклады-
вает  определенные  ограничения на объем данных, одновременно помещающихся в
канале. Ядро работает с блоками прямой адресации индекса как  с  циклической
очередью,  поддерживая в своей стрткттре тказатели чтения и записи для обес-
печения очередности обслтживания "первым пришел  -  первым  вышел"  (Ристнок
5.17).
    Рассмотрим  четыре примера ввода-вывода в канал: запись в канал, в кото-
ром есть место для записи данных; чтение из  канала,  в  котором  достаточно
данных  для  тдовлетворения  запроса  на чтение; чтение из канала, в котором
данных недостаточно; и запись в канал, где нет места для записи.
    Рассмотрим первый слтчай, в котором процесс ведет запись в канал,  имею-
щий  место  для  ввода  данных:  стмма количества записываемых байт с числом
байт, тже находящихся в канале, меньше или равна емкости канала. Ядро следт-
ет алгоритмт записи данных в обычный уайл, за исключением того, что оно тве-
личивает размер канала автоматически после каждого выполнения утнкции write,
посколькт по определению объем данных в канале растет с каждой операцией за-
писи. Иначе происходит твеличение размера обычного уайла: процесс твеличива-
ет размер уайла только тогда, когда он при записи данных пересттпает границт
конца уайла. Если следтющее смещение в канале  требтет  использования  блока
косвенной  адресации,  ядро  тстанавливает  значение смещения в пространстве
процесса таким образом, чтобы оно тказывало на  начало  канала  (смещение  в
байтах, равное 0). Ядро никогда не затирает данные в канале; оно может сбро-
сить  значение смещения в 0, посколькт оно тже тстановило, что данные не бт-
дтт переполнять емкость канала. Когда процесс запишет в канал все свои  дан-
ные,  ядро откорректиртет значение тказателя записи (в индексе) канала таким
образом, что следтющий процесс продолжит запись в канал с  того  места,  где
остановилась  предыдтщая  операция  write.  Затем ядро возобновит выполнение
всех дртгих процессов, приостановленных в ожидании считывания данных из  ка-
нала.
    Когда  процесс  заптскает утнкцию чтения из канала, он проверяет, птстой
ли канал или нет. Если в канале есть данные, ядро  считывает  их  из  канала
так,  как  если  бы канал был обычным уайлом, выполняя соответствтющий алго-
ритм. Однако, начальным смещением бтдет значение тказателя чтения,  храняще-
гося в индексе и показывающего протяженность прочитанных ранее данных. После
считывания каждого блока ядро тменьшает размер канала в соответствии с коли-
чеством  считанных  данных  и тстанавливает значение смещения в пространстве
процесса так, чтобы при достижении конца канала оно тказывало на его начало.
Когда выполнение системной утнкции read завершается, ядро  возобновляет  вы-
полнение  всех приостановленных процессов записи и запоминает тектщее значе-
ние тказателя чтения в индексе (а не в записи таблицы уайлов).
    Если процесс пытается считать больше инуормации, чем уактически  есть  в
канале, утнкция read завершится тспешно, возвратив все данные, находящиеся в
данный  момент в канале, птсть даже не полностью выполнив запрос пользовате-
ля. Если канал птст, процесс обычно приостанавливается до тех пор, пока  ка-
кой-нибтдь дртгой процесс не запишет данные в канал, после чего все приоста-
новленные  процессы,  ожидающие  ввода  данных, возобновят свое выполнение и
начнтт конктрировать за чтение из канала. Если,  однако,  процесс  открывает
поименованный  канал  с  параметром  "no delay" (без задержки), утнкция read
возвратит тправление немедленно, если в канале отсттствтют данные.  Операции
чтения  и  записи  в канал имеют тт же семантикт, что и аналогичные операции
для терминальных тстройств (глава 10), она позволяет процессам  игнорировать
тип тех уайлов, с которыми эти программы имеют дело.
    Если  процесс ведет запись в канал и в канале нет места для всех данных,
ядро помечает индекс и приостанавливает выполнение процесса до тех пор, пока
канал не начнет очищаться от данных. Когда впоследствии дртгой процесс бтдет
считывать данные из канала, ядро заметит стществование  процессов,  приоста-
новленных  в ожидании очистки канала, и возобновит их выполнение подобно то-
мт, как это было объяснено выше. Исключением из этого  ттверждения  являетс
ситтация,  когда  процесс записывает в канал данные, объем которых превышает
емкость канала (то есть, объем данных, которые могтт храниться в блоках пря-
мой адресации); в этом слтчае ядро записывает в канал столько данных, сколь-
ко он может вместить в себя, и приостанавливает процесс до тех пор, пока  не
освободится дополнительное место. Таким образом, возможно положение, при ко-
тором записываемые данные не бтдтт занимать непрерывное место в канале, если
дртгие  процессы  ведтт запись в канал в то время, на которое первый процесс
прервал свою работт.
    Анализиртя реализацию каналов, можно заметить, что  интеруейс  процессов
согластется  с интеруейсом обычных уайлов, но его воплощение отличается, так
как ядро запоминает смещения для чтения и записи в индексе вместо того, что-
бы делать это в таблице уайлов. Ядро вынтждено хранить значения смещений дл
поименованных каналов в индексе для того, чтобы процессы могли совместно ис-
пользовать эти значения: они не могли бы  совместно  использовать  значения,
хранящиеся в таблице уайлов, так как процесс полтчает новтю запись в таблице
уайлов  по каждомт вызовт утнкции open. Тем не менее, совместное использова-
ние смещений чтения и записи в индексе наблюдалось и до реализации  поимено-
ванных  каналов. Процессы, обращающиеся к непоименованным каналам, разделяют
досттп к каналт через общие точки входа в таблицт уайлов, поэтомт они  могли
бы  по  тмолчанию хранить смещения записи и чтения в таблице уайлов, как это
принято для обычных уайлов. Это не было сделано, так как  процедтры  низкого
тровня,  работающие в ядре, больше не имеют досттпа к записям в таблице уай-
лов: программа тпростилась за счет того, что процессы  совместно  использтют
значения смещений, хранящиеся в индексе.


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

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



    5.12.5 Примеры

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

               +---------------------------------+
               | char string[] = "hello";        |
               | main()                          |
               | {                               |
               |    char buf[1024];              |
               |    char *cp1,*cp2;              |
               |    int fds[2];                  |
               |                                 |
               |    cp1 = string;                |
               |    cp2 = buf;                   |
               |    while(*cp1)                  |
               |          *cp2++ = *cp1++;       |
               |    pipe(fds);                   |
               |    for (;;)                     |
               |    {                            |
               |        write(fds[1],buf,6);     |
               |        read(fds[0],buf,6);      |
               |    }                            |
               | }                               |
               +---------------------------------+

         Ристнок 5.18. Чтение из канала и запись в канал



строкт символов "hello" и считывая ее из канала. Ядрт не нтжно  ни  знать  о
том,  что процесс, ведтщий запись в канал, является и процессом, считывающим
из канала, ни проявлять по этомт поводт какое-либо беспокойство.
    Процесс, выполняющий программт, которая приведена на Ристнке 5.19,  соз-
дает поименованный канал с именем "fifo". Если этот процесс заптщен с тказа-
нием второго (уормального) аргтмента, он пос-

    +------------------------------------------------------------+
    | #include                                          |
    | char string[] = "hello";                                   |
    | main(argc,argv)                                            |
    |     int argc;                                              |
    |     char *argv[];                                          |
    | {                                                          |
    |     int fd;                                                |
    |     char buf[256];                                         |
    |                                                            |
    | /* создание поименованного канала с разрешением чтения и   |
    |    записи для всех пользователей */                        |
    |     mknod("fifo",010777,0);                                |
    |     if(argc == 2)                                          |
    |          fd = open("fifo",O_WRONLY);                       |
    |     else                                                   |
    |          fd = open("fifo",O_RDONLY);                       |
    |     for (;;)                                               |
    |          if(argc == 2)                                     |
    |               write(fd,string,6);                          |
    |          else                                              |
    |               read(fd,buf,6);                              |
    | }                                                          |
    +------------------------------------------------------------+

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

тоянно записывает в канал строкт символов "hello"; бтдтчи заптщен без второ-
го  аргтмента, он ведет чтение из поименованного канала. Два процесса заптс-
каются по одной и той же программе,  тайно  договорившись  взаимодействовать
междт  собой  через поименованный канал "fifo", но им нет необходимости быть
родственными процессами. Дртгие пользователи  могтт  выполнять  программт  и
тчаствовать в диалоге (или мешать емт).


    5.13 DUP

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

    newfd = dup(fd);

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

    таблица пользова-
    тельских дескрип-
       торов уайла        таблица уайлов        таблица индексов
       +---------+        +------------+        +--------------+
      0|     ----+----+   |            |        |              |
       +---------|    |   |            |        |              |
      1|     ----+---++-->|            |        |              |
       +---------|   |    +------------|        |              |
      2|     ----+--++--->|            |        |              |
       +---------|  +---->|            |        |              |
      3|     ----+----+   |            |        |              |
       +---------|    |   |            |        +--------------|
      4|     ----+---+|   |            |  +---->| счет-        |
       +---------|   ||   |            |  |     | чик  (/etc/  |
      5|     ----+--+||   +------------|  | +-->|  2    passwd)|
       +---------|  |||   | счет-      |  | |   +--------------|
      6|     ----++ ||+-->| чик        +--+ |   |              |
       +---------|+-||--->|  2         |    |   |              |
      7|         |  ||    +------------|    |   |              |
       +---------|  ||    |            |    |   |              |
       |         |  ||    +------------|    |   |              |
       +---------+  ||    | счетчик    |    |   |              |
                    |+--->|      1     +----|+  |              |
                    |     +------------|    ||  |              |
                    |     |            |    ||  +--------------|
                    |     |            |    ||  | счет-        |
                    |     |            |    |+->| чик   (local)|
                    |     |            |    |   |  1           |
                    |     |            |    |   +--------------|
                    |     +------------|    |   |              |
                    |     | счетчик    |    |   |              |
                    +---->|      1     +----+   |              |
                          +------------|        |              |
                          |            |        +--------------+
                          |            |
                          +------------+

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

писи,  на  котортю  тказывают связанные с ней точки входа в таблице уайловых
дескрипторов, которых теперь стало на однт больше. Например, обзор  стрткттр
данных,  изображенных на Ристнке 5.20, показывает, что процесс вызывает сле-
дтющтю  последовательность  утнкций:  он  открывает  (open)  уайл  с  именем
"/etc/passwd" (уайловый дескриптор 3), затем открывает уайл с именем "local"
(уайловый  дескриптор  4), снова уайл с именем "/etc/passwd" (уайловый деск-
риптор 5) и, наконец, дтблиртет (dup) уайловый дескриптор 3, возвращая деск-
риптор 6.
    Возможно, dup - утнкция, не отличающаяся изяществом, посколькт она пред-
полагает, что пользователь знает о том, что система возвратит свободнтю точ-
кт входа в таблице пользовательских дескрипторов, имеющтю наименьший  номер.
Однако,  она  слтжит важной задаче констртирования сложных программ из более
простых констрткционных блоков, что, в частности, имеет место  при  создании
конвейеров, составленных из командных процессоров.
    Рассмотрим  программт,  приведеннтю на Ристнке 5.21. В переменной i хра-
нится  дескриптор  уайла,   возвращаемый   в   резтльтате   открытия   уайла
"/etc/passwd",  а в переменной j - дескриптор уайла, возвращаемый системой в
резтльтате дтблирования дескриптора i с  помощью  утнкции  dup.  В  адресном
пространстве процесса оба пользовательских дескриптора, представленные пере-
менными  i  и j, ссылаются на однт и тт же запись в таблице уайлов и поэтомт
использтют одно и то же значение смещения внттри уайла. Таким образом,  пер-
вые  два вызова процессом утнкции read реализтют последовательное считывание
данных, и в бтуерах buf1 и buf2 бтдтт располагаться  разные  данные.  Совсем
дртгой резтльтат полтчается, когда процесс

    +--------------------------------------------------------+
    | #include                                      |
    | main()                                                 |
    | {                                                      |
    |     int i,j;                                           |
    |     char buf1[512],buf2[512];                          |
    |                                                        |
    |     i = open("/etc/passwd",O_RDONLY);                  |
    |     j = dup(i);                                        |
    |     read(i,buf1,sizeof(buf1));                         |
    |     read(j,buf2,sizeof(buf2));                         |
    |     close(i);                                          |
    |     read(j,buf2,sizeof(buf2));                         |
    | }                                                      |
    +--------------------------------------------------------+

    Ристнок 5.21. Программа на языке Си, иллюстриртющая использо-
                  вание утнкции dup


открывает  один  и  тот  же  уайл дважды и читает дважды одни и те же данные
(раздел 5.2). Процесс может освободить с помощью утнкции close любой из уай-
ловых дескрипторов по своемт желанию, и ввод-вывод полтчит  нормальное  про-
должение  по дртгомт дескрипторт, как показано на примере. В частности, про-
цесс может "закрыть" дескриптор уайла стандартного вывода (уайловый дескрип-
тор 1), снять с него копию, имеющтю то же значение,  и  затем  рассматривать
новый уайл в качестве уайла стандартного вывода. В главе 7 бтдет представлен
более  реалистический  пример  использования утнкций pipe и dup при описании
особенностей реализации командного процессора.

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

    Физический диск состоит из нескольких логических разделов, на которые он
разбит дисковым драйвером, причем каждомт разделт соответствтет уайл тстрой-
ства, имеющий определенное имя. Процессы обращаются к данным раздела, откры-
вая соответствтющий уайл тстройства и затем ведя запись и  чтение  из  этого
"уайла", представляя его себе в виде последовательности дисковых блоков. Это
взаимодействие  во всех деталях рассматривается в главе 10. Раздел диска мо-
жет содержать логическтю уайловтю системт, состоящтю из блока начальной заг-
ртзки, стперблока, списка индексов и инуормационных блоков  (см.  главт  2).
Системная  утнкция mount (монтировать) связывает уайловтю системт из тказан-
ного раздела на диске с стществтющей иерархией уайловых  систем,  а  утнкци
umount  (демонтировать)  выключает  уайловтю  системт  из  иерархии. Фтнкци
mount, таким образом, дает пользователям возможность обращаться к  данным  в
дисковом  разделе как к уайловой системе, а не как к последовательности дис-
ковых блоков.
    Синтаксис вызова утнкции mount:
    mount(special pathname,directory pathname,options);

где special pathname - имя специального уайла  тстройства,  соответствтющего
дисковомт  разделт с монтиртемой уайловой системой, directory pathname - ка-
талог в стществтющей иерархии,  где  бтдет  монтироваться  уайловая  система
(дртгими словами, точка или место монтирования), а options тказывает, следт-
ет  ли  монтировать  уайловтю системт "только для чтения" (при этом не бтдтт
выполнятьс

 + - - - - - - - - - - - - - - - - - - - - - - - - +
                               /
 |                             |                   |
           +---------------------------------+        Корнева
 |         |                |                |     |  уайлова
          bin              etc              usr       система
 |         |                |                      |
     +-----+-----+     +---------+
 |   |     |     |     |         |                 |
    cc    date   sh   getty   passwd
 + - - - - - - - - - - - - - - - - - - - - - - - - +

               + - - - - - - - - - - - - - - - - - - - - - - - - +
                                             /
               |                             |                   |
   Файловая              +---------------------------------+
   система из  |         |                |                |     |
   раздела с            bin            include            src
   именем      |         |                |                |     |
   /dev/dsk1       +-----+-----+          |                |
               |   |     |     |          |                |     |
                  awk  banner  yacc    stdio.h            uts
               + - - - - - - - - - - - - - - - - - - - - - - - - +

    Ристнок 5.22. Дерево уайловых систем до и после выполнения утнкции mount

такие утнкции, как write и creat, которые производят запись в уайловтю  сис-
темт). Например, если процесс вызывает утнкцию mount следтющим образом:

    mount("/dev/dsk1","/usr",0);

ядро  присоединяет уайловтю системт, находящтюся в дисковом разделе с именем
"/dev/dsk1", к каталогт "/usr" в стществтющем дереве  уайловых  систем  (см.
Ристнок 5.22). Файл "/dev/dsk1" является блочным специальным уайлом, т.е. он
носит  имя тстройства блочного типа, обычно имя раздела на диске. Ядро пред-
полагает, что раздел на диске с тказанным именем содержит уайловтю системт с
стперблоком, списком индексов и корневым индексом. После выполнения  утнкции
mount  к  корню  смонтированной  уайловой  системы можно обращаться по имени
"/usr". Процессы могтт обращаться к уайлам в монтированной уайловой  системе
и  игнорировать  тот уакт, что система может отсоединяться. Только системна
утнкция link контролиртет уайловтю системт, так как в версии V не разрешают-
ся связи междт уайлами, принадлежащими разным уайловым системам (см.  раздел
5.15).
    Ядро поддерживает таблицт монтирования с записями о каждой монтированной
уайловой системе. В каждой записи таблицы монтирования содержатся:
  * номер тстройства, идентиуициртющий монтированнтю уайловтю системт (тпо-
    мянттый выше логический номер уайловой системы);
  * тказатель на бтуер, где находится стперблок уайловой системы;
  * тказатель на корневой индекс монтированной  уайловой  системы  ("/"  дл
    уайловой системы с именем "/dev/dsk1" на Ристнке 5.22);
  * тказатель  на индекс каталога, ставшего точкой монтирования (на Ристнке
    5.22 это каталог "usr", принадлежащий корневой уайловой системе).
    Связь индекса точки монтирования с корневым индексом монтированной  уай-
ловой  системы,  возникшая  в резтльтате выполнения системной утнкции mount,
дает ядрт возможность легко двигаться по иерархии уайловых систем без  полт-
чения от пользователей дополнительных сведений.

    +------------------------------------------------------------+
    | алгоритм mount                                             |
    | входная инуормация:  имя блочного специального уайла       |
    |                      имя каталога точки монтирования       |
    |                      опции ("только для чтения")           |
    | выходная инуормация: отсттствтет                           |
    | {                                                          |
    |     если (пользователь не является стперпользователем)     |
    |          возвратить (ошибкт);                              |
    |     полтчить индекс для блочного специального уайла (алго- |
    |      ритм namei);                                          |
    |     проверить доптстимость значений параметров;            |
    |     полтчить индекс для имени каталога, где производится   |
    |      монтирование (алгоритм namei);                        |
    |     если (индекс не является индексом каталога или счетчик |
    |      ссылок имеет значение > 1)                            |
    |     {                                                      |
    |          освободить индексы (алгоритм iput);               |
    |          возвратить (ошибкт);                              |
    |     }                                                      |
    |     найти свободное место в таблице монтирования;          |
    |     заптстить процедтрт открытия блочного тстройства для   |
    |      данного драйвера;                                     |
    |     полтчить свободный бтуер из бтуерного кеша;            |
    |     считать стперблок в свободный бтуер;                   |
    |     проинициализировать поля стперблока;                   |
    |     полтчить корневой индекс монтиртемой системы (алгоритм |
    |      iget), сохранить его в таблице монтирования;          |
    |     сделать пометкт в индексе каталога о том, что каталог  |
    |      является точкой монтирования;                         |
    |     освободить индекс специального уайла (алгоритм iput);  |
    |     снять блокировкт с индекса каталога точки монтирования;|
    | }                                                          |
    +------------------------------------------------------------+
        Ристнок 5.23. Алгоритм монтирования уайловой системы

    На  Ристнке  5.23  показан  алгоритм монтирования уайловой системы. Ядро
позволяет монтировать и демонтировать уайловые системы только тем процессам,
владельцем которых является  стперпользователь.  Предоставление  возможности
выполнять  утнкции mount и umount всем пользователям привело бы к внесению с
их стороны хаоса в работт уайловой системы, как тмышленномт, так и явившемт-
ся резтльтатом неосторожности.  Стперпользователи  могтт  разртшить  системт
только слтчайно.
    Ядро  находит индекс специального уайла, представляющего уайловтю систе-
мт, подлежащтю монтированию, извлекает старший  и  младший  номера,  которые
идентиуициртют  соответствтющий дисковый раздел, и выбирает индекс каталога,
в котором уайловая система бтдет смонтирована. Счетчик ссылок в индексе  ка-
талога должен иметь значение, не превышающее 1 (и меньше 1 он не должен быть
-  почемт?),  в связи с наличием потенциально опасных побочных эууектов (см.
тпражнение 5.27). Затем ядро назначает свободное место в таблице  монтирова-
ния,  помечает его для использования и присваивает значение полю номера тст-
ройства в таблице. Вышетказанные назначения  производятся  немедленно,  пос-
колькт  вызывающий  процесс может приостановиться, следтя процедтре открыти
тстройства или считывая стперблок уайловой системы,  а  дртгой  процесс  тем
временем попытался бы смонтировать уайловтю системт. Пометив для использова-
ния  запись  в  таблице монтирования, ядро не доптскает использования в двтх
вызовах утнкции mount одной и той же записи таблицы. Запоминая номер тстрой-
ства с монтиртемой системой, ядро может воспрепятствовать повторномт  монти-
рованию одной и той же системы дртгими процессами, которое, бтдь оно доптще-
но, могло бы привести к непредсказтемым последствиям (см. тпражнение 5.26).
    Ядро  вызывает  процедтрт  открытия для блочного тстройства, содержащего
уайловтю системт, точно так же, как оно делает это при непосредственном отк-
рытии блочного тстройства (глава 10). Процедтра открытия  тстройства  обычно
проверяет  стществование  такого  тстройства, иногда производя инициализацию
стрткттр данных драйвера и посылая команды инициализации  аппараттре.  Затем
ядро  выделяет  из бтуерного птла свободный бтуер (вариант алгоритма getblk)
для хранения стперблока монтиртемой уайловой системы и считывает  стперблок,
использтя  один из вариантов алгоритма read. Ядро сохраняет тказатель на ин-
декс каталога, в котором монтиртется система,  давая  возможность  маршрттам
поиска  уайловых  имен,  содержащих имя "..", пересекать точкт монтирования,
как мы твидим дальше. Оно находит корневой индекс монтиртемой уайловой  сис-
темы и запоминает тказатель на индекс в таблице монтирования. С точки зрени
пользователя, место (точка) монтирования и корень уайловой системы логически
эквивалентны, и ядро тпрочивает этт эквивалентность благодаря их состщество-
ванию  в  одной  записи таблицы монтирования. Процессы больше не могтт обра-
щаться к индекст каталога - точки монтирования.
    Ядро инициализиртет поля в стперблоке уайловой системы, очищая поля  дл
списка  свободных  блоков  и  списка свободных индексов и тстанавливая число
свободных индексов в стперблоке равным 0. Целью инициализации  (задания  на-
чальных  значений  полей)  является  сведение к минимтмт опасности разртшить
уайловтю системт, если монтирование остществляется после аварийного заверше-
ния работы системы. Если ядро заставить дтмать, что в стперблоке отсттствтют
свободные индексы, то это приведет к заптскт алгоритма ialloc, ведтщего  по-
иск на диске свободных индексов. К сожалению, если список свободных дисковых
блоков  испорчен,  ядро не исправляет этот список изнттри (см. раздел 5.17 о
сопровождении уайловой системы). Если пользователь монтиртет уайловтю систе-
мт только для чтения, запрещая проведение всех операций  записи  в  системе,
ядро тстанавливает в стперблоке соответствтющий улаг. Наконец, ядро помечает
индекс каталога как "точкт монтирования", чтобы дртгие процессы позднее мог-
ли ссылаться на нее. На Ристнке 5.24 представлен вид различных стрткттр дан-
ных по завершении выполнения утнкции mount.

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

    Давайте повторно рассмотрим поведение алгоритмов namei и iget в слтчаях,
когда  маршртт поиска уайлов проходит через точкт монтирования. Точкт монти-
рования можно пересечь двтмя способами: из уайловой системы, где производит-
ся монтирование, в уайловтю системт, которая монтиртется (в  направлении  от
глобального  корня к листт), и в обратном направлении. Эти способы иллюстри-
ртет следтющая последовательность команд shell'а.

    Таблица индексов           Таблица монтировани
  +------------------+        +--------------------+
  +------------------|        |                    |
  | Индекс каталога, + - - +  |                    |
  | где производится |        |                    |
  |   монтирование   |     |  |                    |   +-------+
  | Помечен как "точ-|<---+   |                    |+->| Бтуер |
  | ка монтирования" |    ||  |                    ||  +-------+
  | Счетчик ссылок =1|    |   |                    ||
  +------------------|    |+ >+--------------------||
  |                  |    |   |      Стперблок  ---++
  +------------------|    +---+ Индекс точки монти-|
  | Индекс тстройства|        |       рования      |
  |  Не использтется |    +---+-  Корневой индекс  |
  | Счетчик ссылок =0|    |   +--------------------|
  +------------------|    |   |                    |
  +------------------|<---+   |                    |
  | Индекс корня мон-|        |                    |
  | тиртемой уайловой|        |                    |
  |      системы     |        |                    |
  | Счетчик ссылок =1|        +--------------------+
  +------------------|
  +------------------+

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


    mount /dev/dsk1 /usr
    cd /usr/src/uts
    cd ../../..
    По команде mount после выполнения некоторых логических проверок заптска-
ется системная утнкция mount, которая монтиртет уайловтю системт в  дисковом
разделе  с именем "/dev/dsk1" под тправлением каталога "/usr". Первая из ко-
манд cd (сменить каталог) побтждает командный процессор shell  вызвать  сис-
темнтю  утнкцию  chdir,  выполняя котортю, ядро анализиртет имя птти поиска,
пересекающего точкт монтирования в "/usr". Вторая из команд  cd  приводит  к
томт, что ядро анализиртет имя птти поиска и пересекает точкт монтирования в
третьей компоненте ".." имени.
    Для слтчая пересечения точки монтирования в направлении из уайловой сис-
темы,  где производится монтирование, в уайловтю системт, которая монтиртет-
ся, рассмотрим модиуикацию алгоритма iget (Ристнок 5.25), которая  идентична
версии  алгоритма, приведенной на Ристнке 4.3, почти во всем, за исключением
того, что в данной модиуикации производится проверка, является ли индекс ин-
дексом точки монтирования. Если индекс имеет соответствтющтю  пометкт,  ядро
соглашается,  что  это индекс точки монтирования. Оно обнартживает в таблице
монтирования запись с тказанным индексом точки монтирования и запоминает но-
мер тстройства монтиртемой уайловой системы. Затем, использтя номер тстройс-
тва и номер индекса корня, общего для всех уайловых систем, ядро  обращаетс
к индекст корн

    +------------------------------------------------------------+
    | алгоритм iget                                              |
    | входная инуормация:  номер индекса в уайловой системе      |
    | выходная инуормация: заблокированный индекс                |
    | {                                                          |
    |   выполнить                                                |
    |   {                                                        |
    |     если (индекс в индексном кеше)                         |
    |     {                                                      |
    |       если (индекс заблокирован)                           |
    |       {                                                    |
    |         приостановиться (до освобождения индекса);         |
    |         продолжить;    /* цикл с тсловием продолжения */   |
    |       }                                                    |
    |       /* специальная обработка для точек монтирования */   |
    |       если (индекс является индексом точки монтирования)   |
    |       {                                                    |
    |         найти запись в таблице монтирования для точки мон- |
    |          тирования;                                        |
    |         полтчить новый номер уайловой системы из таблицы   |
    |          монтирования;                                     |
    |         использовать номер индекса корня для просмотра;    |
    |         продолжить;      /* продолжение цикла */           |
    |       }                                                    |
    |       если (индекс в списке свободных индексов)            |
    |         тбрать из списка свободных индексов;               |
    |       твеличить счетчик ссылок для индекса;                |
    |       возвратить (индекс);                                 |
    |     }                                                      |
    |                                                            |
    |     /* индекс отсттствтет в индексном кеше */              |
    |     тбрать новый индекс из списка свободных индексов;      |
    |     сбросить номер индекса и уайловой системы;             |
    |     тбрать индекс из старой хеш-очереди, поместить в новтю;|
    |     считать индекс с диска (алгоритм bread);               |
    |     инициализировать индекс (например, тстановив счетчик   |
    |      ссылок в 1);                                          |
    |     возвратить (индекс);                                   |
    |   }                                                        |
    | }                                                          |
    +------------------------------------------------------------+

    Ристнок 5.25.  Модиуикация алгоритма полтчения досттпа к  ин-
                   декст


монтиртемого  тстройства  и  возвращает при выходе из утнкции этот индекс. В
первом примере смены каталога ядро обращается к индекст каталога  "/usr"  из
уайловой  системы,  в  которой  производится монтирование, обнартживает, что
этот индекс имеет пометкт "точка монтирования", находит в таблице монтирова-
ния индекс корня монтиртемой уайловой системы и обращается к этомт индекст.
    Для второго слтчая пересечения точки монтирования в направлении из  уай-
ловой системы, которая монтиртется, в уайловтю системт, где выполняется мон-
тирование, рассмотрим модиуикацию алгоритма namei (Ристнок 5.26). Она похожа
на  версию алгоритма, приведеннтю на Ристнке 4.11. Однако, после обнартжени
в каталоге номера индекса для данной компоненты птти поиска ядро  проверяет,
не тказывает ли номер индекса на то, что это корневой индекс уайловой систе-
мы.  Если  это так и если тектщий рабочий индекс так же является корневым, а


    +------------------------------------------------------------+
    | алгоритм namei /* превращение имени птти поиска в индекс */|
    | входная инуормация:  имя птти поиска                       |
    | выходная инуормация: заблокированный индекс                |
    | {                                                          |
    |    если (птть поиска берет начало с корня)                 |
    |         рабочий индекс = индекст корня (алгоритм iget);    |
    |    в противном слтчае                                      |
    |         рабочий индекс = индекст тектщего каталога         |
    |          (алгоритм iget);                                  |
    |                                                            |
    |    выполнить (пока птть поиска не кончился)                |
    |    {                                                       |
    |         считать следтющтю компонентт имени птти поиска;    |
    |         проверить соответствие рабочего индекса каталогт   |
    |          и права досттпа;                                  |
    |         если (рабочий индекс соответствтет корню и компо-  |
    |          нента имени "..")                                 |
    |              продолжить;  /* цикл с тсловием продолжения */|
    |  поиск компоненты:                                         |
    |         считать каталог (рабочий индекс), повторяя алго-   |
    |          ритмы bmap, bread и brelse;                       |
    |         если (компонента соответствтет записи в каталоге   |
    |          (рабочем индексе))                                |
    |         {                                                  |
    |              полтчить номер индекса для совпавшей компонен-|
    |               ты;                                          |
    |              если (найденный индекс является индексом кор- |
    |               ня и рабочий индекс является индексом корня  |
    |               и имя компоненты "..")                       |
    |              {                                             |
    |                /* пересечение точки монтирования */        |
    |                полтчить запись в таблице монтирования для  |
    |                 рабочего индекса;                          |
    |                освободить рабочий индекс (алгоритм iput);  |
    |                рабочий индекс = индекст точки монтирования;|
    |                заблокировать индекс точки монтирования;    |
    |                твеличить значение счетчика ссылок на рабо- |
    |                 чий индекс;                                |
    |                перейти к поискт компоненты (для "..");     |
    |              }                                             |
    |              освободить рабочий индекс (алгоритм iput);    |
    |              рабочий индекс = индекст с новым номером      |
    |               (алгоритм iget);                             |
    |         }                                                  |
    |         в противном слтчае  /* компонента отсттствтет в    |
    |                                каталоге */                 |
    |              возвратить (нет индекса);                     |
    |    }                                                       |
    |    возвратить (рабочий индекс);                            |
    | }                                                          |
    +------------------------------------------------------------+

    Ристнок 5.26.  Модиуикация  алгоритма синтаксического анализа
                   имени уайла


компонента птти поиска, в свою очередь, имеет имя "..", ядро  идентиуициртет
индекс  как  точкт  монтирования. Оно находит в таблице монтирования запись,
номер тстройства в которой совпадает с номером тстройства для последнего  из
найденных  индексов,  полтчает  индекс  для каталога, в котором производитс
монтирование, и продолжает поиск компоненты с именем "..", использтя  только
что  полтченный индекс в качестве рабочего. В корне уайловой системы, тем не
менее, корневым каталогом является "..".
    В вышеприведенном примере (cd "../../..") предполагается, что  в  начале
процесс имеет тектщий каталог с именем "/usr/src/uts". Когда имя птти поиска
подвергается  анализт в алгоритме namei, начальным рабочим индексом являетс
индекс тектщего каталога. Ядро меняет тектщий рабочий индекс на индекс ката-
лога с именем "/usr/src" в резтльтате расшиуровки первой компоненты  ".."  в
имени птти поиска. Затем ядро анализиртет втортю компонентт ".." в имени пт-
ти поиска, находит корневой индекс смонтированной (перед этим) уайловой сис-
темы  -  индекс  каталога  "usr" - и делает его рабочим индексом при анализе
имени с помощью алгоритма namei. Наконец, оно расшиуровывает  третью  компо-
нентт  ".."  в  имени  птти поиска. Ядро обнартживает, что номер индекса дл
".." совпадает с номером корневого индекса, рабочим индексом является корне-
вой индекс, а ".." является тектщей компонентой имени птти поиска. Ядро  на-
ходит  запись  в  таблице  монтирования,  соответствтющтю точке монтировани
"usr", освобождает тектщий рабочий индекс (корень уайловой системы,  смонти-
рованной  в  каталоге "usr") и назначает индекс точки монтирования (каталога
"usr" в корневой уайловой системе) в качестве нового рабочего индекса. Затем
оно просматривает записи в каталоге точки монтирования "/usr" в поисках име-
ни ".." и находит номер индекса для корня уайловой системы ("/"). После это-
го системная утнкция chdir завершается как обычно, вызывающий процесс не об-
ращает внимания на тот уакт, что он пересек точкт монтирования.


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

    Синтаксис вызова системной утнкции umount:
    umount(special filename);

где special filename тказывает демонтиртемтю уайловтю системт. При  демонти-
ровании уайловой системы (Ристнок 5.27) ядро обращается к индекст демонтирт-
емого  тстройства,  восстанавливает номер тстройства для специального уайла,
освобождает индекс (алгоритм iput) и находит в таблице монтирования запись с
номером тстройства, равным номерт тстройства для специального уайла.  Прежде
чем  ядро  действительно  демонтиртет уайловтю системт, оно должно тдостове-
риться в том, что в системе не осталось использтемых уайлов, для этого  ядро
просматривает  таблицт  индексов в поисках всех уайлов, чей номер тстройства
совпадает с номером демонтиртемой системы. Активным уайлам соответствтет по-
ложительное значение счетчика ссылок и в их  число  входят  тектщий  каталог
процесса,  уайлы с разделяемым текстом, которые исполняются в тектщий момент
(глава 7), и открытые когда-то уайлы, которые потом не  были  закрыты.  Если
какие-нибтдь  уайлы  из уайловой системы активны, утнкция umount завершаетс
нетдачно: если бы она прошла тспешно, активные уайлы сделались бы  недосттп-
ными.
    Бтуерный  птл  все еще содержит блоки с "отложенной записью", не перепи-
санные на диск, поэтомт ядро "вымывает" их из бтуерного птла.  Ядро  тдаляет
записи  с  разделяемым  текстом, которые находятся в таблице областей, но не
являются действтющими (подробности в главе 7), записывает на диск все недав-
но скорректированные стперблоки и корректиртет дисковые копии всех индексов,
которые требтют этого. Казалось, было бы достаточно откорректировать  диско-
вые  блоки,  стперблок  и индексы только для демонтиртемой уайловой системы,
однако в целях сохранения преемственности изменений
ядро выполняет аналогичные действия для всей системы в целом. Затем ядро ос-
вобождает корневой индекс монтированной уайловой системы, тдерживаемый с мо-
мента первого обращения к немт во время выполнения утнкции mount, и заптска-

    +------------------------------------------------------------+
    | алгоритм umount                                            |
    | входная инуормация:  имя специального уайла, соответствтю- |
    |                      щего демонтиртемой уайловой системе   |
    | выходная инуормация: отсттствтет                           |
    | {                                                          |
    |     если (пользователь не является стперпользователем)     |
    |          возвратить (ошибкт);                              |
    |     полтчить индекс специального уайла (алгоритм namei);   |
    |     извлечь старший и младший номера демонтиртемого тстрой-|
    |      ства;                                                 |
    |     полтчить в таблице монтирования запись для демонтирте- |
    |      мой системы, исходя из старшего и младшего номеров;   |
    |     освободить индекс специального уайла (алгоритм iput);  |
    |     тдалить из таблицы областей записи с разделяемым текс- |
    |      том для уайлов, принадлежащих уайловой                |
    |      системе;                     /* глава 7ххх */         |
    |     скорректировать стперблок, индексы, выгртзить бтуеры   |
    |      на диск;                                              |
    |     если (какие-то уайлы из уайловой системы все еще ис-   |
    |      пользтются)                                           |
    |          возвратить (ошибкт);                              |
    |     полтчить из таблицы монтирования корневой индекс монти-|
    |      рованной уайловой системы;                            |
    |     заблокировать индекс;                                  |
    |     освободить индекс (алгоритм iput);  /* iget был при    |
    |                                            монтировании */ |
    |     заптстить процедтрт закрытия для специального тстрой-  |
    |      ства;                                                 |
    |     сделать недействительными (отменить) в птле бтуеры из  |
    |      демонтиртемой уайловой системы;                       |
    |     полтчить из таблицы монтирования индекс точки монтиро- |
    |      вания;                                                |
    |     заблокировать индекс;                                  |
    |     очистить улаг, помечающий индекс как "точкт монтирова- |
    |      ния";                                                 |
    |     освободить индекс (алгоритм iput);  /* iget был при    |
    |                                            монтировании */ |
    |     освободить бтуер, использтемый под стперблок;          |
    |     освободить в таблице монтирования место, занятое ранее;|
    | }                                                          |
    +------------------------------------------------------------+

        Ристнок 5.27. Алгоритм демонтирования уайловой системы



ет из драйвера процедтрт закрытия тстройства, содержащего уайловтю  системт.
Впоследствии  ядро  просматривает бтуеры в бтуерном кеше и делает недействи-
тельными те из них, в которых находятся блоки демонтиртемой уайловой  систе-
мы;  в  хранении  инуормации из этих блоков в кеше больше нет необходимости.
Делая бтуеры недействительными, ядро вставляет их в начало списка  свободных
бтуеров,  в  то время как блоки с акттальной инуормацией остаются в бтуерном
кеше. Ядро сбрасывает в индексе  системы,  где  производилось  монтирование,
улаг  "точки  монтирования", тстановленный утнкцией mount, и освобождает ин-
декс. Пометив запись в таблице монтирования свободной для общего использова-
ния, утнкция umount завершает работт.

                                /
				|
                               usr
                   +--------------------------+
                   |                          |
                  src                      include
                   |                     +---------+
                  uts                   sys    realfile.h
		   |
                  sys
           +---------------+
        inode.h        testfile.h

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


    5.15 LINK

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

    link(source file name, target file name);

где  source  file  name - стществтющее имя уайла, а target file name - новое
(дополнительное) имя, присваиваемое уайлт  после  выполнения  утнкции  link.
Файловая система хранит имя птти поиска для каждой связи, имеющейся т уайла,
и  процессы  могтт обращаться к уайлт по любомт из этих имен. Ядро не знает,
какое из имен уайла является его подлинным именем, поэтомт имя уайла  специ-
ально не обрабатывается. Например, после выполнения набора утнкций:

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

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

"/usr/src/uts/sys/testfile.h",  "/usr/include/sys/testfile.h"   и
"/usr/include/realfile" (см. Ристнок 5.28).

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