Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ОСиС_2008

.pdf
Скачиваний:
96
Добавлен:
29.05.2015
Размер:
2.65 Mб
Скачать

6. Управление файлами

227

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

Перечисленные поля дескрипторов элементов буфера КЭШа используются подпрограммами КЭШа при выполнении запросов программных частей реальных ФС на выполнение операций информационного обмена с устройствами ВП. При этом многие из этих полей используются для организации интерфейса между КЭШем и подсистемой ввода-вывода.

Например, запрос на чтение блока от реальной ФС содержит параметры: 1) системное имя устройства, в качестве которого используется пара чисел (старший номер устройства; младший номер устройства); 2) номер требуемого блока на устройстве; 3) длину блока информационной части реальной ФС (в секторах); 4) начальный виртуальный адрес той области ОП процесса, в которую требуется выполнить считывание блока. Получив данный запрос, программа КЭШа определяет системное имя первого сектора требуемого блока в виде тройки чисел (старший номер устройства; младший номер устройства; номер сектора на устройстве). Далее выполняется поиск дескриптора элемента буфера, поля которого содержат указанную тройку чисел. Если поиск завершился успешно, то содержимое заданного числа элементов буфера КЭШа переписывается в прикладную область процесса.

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

Заметим, что для формирования запроса к подсистеме вводавывода на считывание сектора программа КЭШа создает деск-

228

Одиноков В.В., Коцубинский В.П.

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

Что касается нового элемента буфера, предназначенного для размещения сектора, считываемого с диска, то он выбирается из начала списка свободных элементов. Данный список представляет собой двухсвязанную очередь, образованную с помощью двух указателей, находящихся в одном из полей элемента буфера КЭШа. Список свободных элементов содержит все элементы буфера КЭШа, у которых сброшен флаг активности и которые, следовательно, в данный момент времени не участвуют ни в одной операции информационного обмена с диском. Если элемент буфера КЭШа участвует в какой-то такой операции, то сразу же после ее завершения он будет помещен в конец списка свободных элементов. В случае начала другой такой операции этот элемент опять покинет список на время выполнения операции.

Допустим, что из реальной ФС поступил запрос выполнить запись какого-то блока файла на диск. В этом случае программа КЭШа определяет наличие соответствующих элементов в своем буфере. Если такие элементы уже есть, то в качестве их содержимого записывается информация из прикладной области, заданной в запросе реальной ФС. Иначе перед тем как выполнять запись, осуществляется выборка требуемого числа элементов из списка свободных элементов. В любом случае производится установка флага модификации элемента буфера. Так как содержимое этих модифицированных элементов буфера отличается от соответствующих дисковых секторов, то их необходимо время от времени переписывать на диск. Подобную операцию будем называть син-

хронизацией КЭШа.

Нетрудно заметить, что для повышения надежности ФС необходимо проводить синхронизацию КЭШа как можно чаще. С другой стороны, для повышения производительности системы такую синхронизацию следует выполнять реже. Инициирование синхронизации КЭШа выполняется тремя способами. При первом из них причиной синхронизации является системный вызов

СИНХРОНИЗИРОВАТЬ_КЭШ ( || ) (на СИ — sync).

6. Управление файлами

229

При получении данного системного вызова программа КЭШа передает в подсистему ввода-вывода для записи на диск все модифицированные элементы буфера КЭШа. При этом для каждого переданного элемента выполняется сброс флага модификации. Источником данного системного вызова является утилита sync, запускаемая по команде суперпользователя.

Второй причиной синхронизации КЭШа является процесс ядра, входящий в состав КЭШа, который инициируется через фиксированные промежутки времени с помощью отложенных вызовов (см. подразд. 4.5). Данный процесс ядра обеспечивает сброс на диск всех модифицированных элементов буфера КЭШа.

Третий способ синхронизации КЭШа заключается в том, что системный вызов открытия файла, выданный прикладным процессом, в качестве входного параметра содержит флаг «синхронный». В этом случае все операции записи в открытый таким образом файл приведут к немедленной записи данных на диск.

6.4.2. Использование подсистемы управления памятью

Любая UNIX-система имеет подсистему управления памятью, принципы работы которой были рассмотрены нами в гл. 5. Входящие в эту подсистему подпрограммы, а также аппаратные средства, предназначенные для поддержки линейной виртуальной памяти, фактически реализуют дисковое кэширование. Это обусловлено, во-первых, тем, что реализация линейной виртуальной памяти предполагает отображение файла, содержащего загрузочный модуль программы, на множество логических страниц созданного процесса. При этом часть этих логических страниц (и соответствующих им фрагментов файла) загружается в физические страницы ОП. Во-вторых, логические страницы программы, содержащие ее данные, перемещаются в результате страничного свопинга между ОП и областью свопинга на системном устройстве ВП. В-третьих, система управления памятью используется для реализации отображения файлов на области виртуальной ОП (см.

п. 6.1.3).

Для того чтобы организовать КЭШ на основе подсистемы управления памятью, достаточно организовать отображение дисковых файлов не на прикладную часть линейной виртуальной ОП (как при выполнении системного вызова отображения файла), а на системную часть этой памяти. Это отображение скрыто от про-

230

Одиноков В.В., Коцубинский В.П.

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

1)номер vnode файла;

2)величину смещения в файле, начиная с которого данные файла отображаются на ОП;

3)смещение относительно начала сегмента отображений — относительный адрес, начиная с которого располагается область отображения файла.

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

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

6. Управление файлами

231

Предельная длина одной области отображения, равная 8096 × × 512 байтов, обусловлена требованием использования единственной таблицы страниц для установки соответствия между этой виртуальной областью и реальной ОП. Напомним, что таблица страниц содержит 1024 дескрипторов страниц, каждая из которых имеет длину 4096 байтов. Поэтому общая длина области виртуальной ОП, поддерживаемая одной таблицей страниц, составляет 1024 × 4096 = 8096 × 512 байтов = 4096 кбайтов. Выделение данной виртуальной памяти, конечно, не означает назначения реальной ОП, так как лишь некоторым из 1024 логических страниц области отображения файла будут соответствовать реальные физические страницы ОП.

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

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

7. ПОДСИСТЕМА ВВОДА-ВЫВОДА

7.1. Предоставляемый интерфейс

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

В состав ПВВ входит модуль управления драйверами, а также сами драйверы. Функцией модуля управления драйверами явля-

ется согласование вышестоящих подсистем ядра (ФС, КЭШ, подсистемы управления памятью) с драйверами. Каждый драйвер выполняет управление периферийными устройствами одного типа. В ВС обязательно имеются драйвер экрана, драйвер клавиатуры, драйвер дисковода (для каждого типа дисководов свой драйвер) и многие другие драйверы. На рис. 55 приведена укрупненная схема управления ПУ, рассмотрение которой весьма полезно для выявления функций ПВВ.

Во-первых, обратим внимание, что в состоянии «Задача» процесс не имеет непосредственного доступа к ПВВ. Такой доступ возможен только через файловую систему. Причем доступ к устройствам ввода-вывода выполняется с помощью операций над специальными файлами устройств (расположены в каталоге /dev). А доступ к устройствам внешней памяти возможен двумя способами: 1) с помощью операций над файлами данных; 2) с помощью операций с файлами устройств. Второй способ используется, например, при копировании содержимого одного диска на другой диск, так как в этом случае файловое содержимое копируемого диска не представляет интереса.

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

ОТКРЫТЬ_ФАЙЛ_УСТРОЙСТВА (I || i) (на СИ — open); ЗАКРЫТЬ_ФАЙЛ_УСТРОЙСТВА (i || ) ( –//– close);

7. Подсистема ввода-вывода

233

ЧТЕНИЕ_ФАЙЛА_УСТРОЙСТВА (i, A, n || ) ( –//– read); ЗАПИСЬ_ФАЙЛ_УСТРОЙСТВА (i, A, n || ) ( –//– write),

где I — имя файла-устройства (примеры таких имен: 1) /dev/cd0 CD-ROM с номером 0; 2) /dev/lp3 — параллельный порт с номером 3); i — программное имя (номер) файла, уникальное для данного процесса (после открытия файла-устройства номер i используется в программе процесса как идентификатор этого файла); A — начальный адрес прикладного буфера, в который производится чтение из файла-устройства или из которого производится запись на устройство; n — число байтов, считываемых с устройства или записываемых на него.

Процесс 1

. . .

Процесс n

 

 

 

 

Файловая

 

 

 

 

 

 

 

Подсистема

 

 

 

 

 

 

 

 

 

 

система

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

управления

 

 

 

 

 

 

Специальные

 

 

 

 

 

 

 

 

 

 

 

памятью

 

 

 

 

 

 

 

файлы

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Дисковый

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

КЭШ

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Верхний

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

интерфейс

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ПВВ

 

 

Коммутатор

Управление

 

Коммутатор

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

строчных

драйверами

 

 

блочных

 

 

 

 

 

 

 

 

 

 

 

 

драйверов

 

 

драйверов

 

 

 

 

 

ПВВ

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Строчный

Драйверы

 

 

Блочный

 

 

 

 

 

 

 

 

 

 

 

 

 

драйвер

 

 

 

драйвер

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Нижний

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

интерфейс

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ПВВ

 

 

 

 

ИУ1

 

 

 

 

 

 

ИУr

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ПУ1

 

 

ПУ1r

 

. . .

 

 

 

ПУkr

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 55. Укрупненная схема управления периферийными устройствами

234

Одиноков В.В., Коцубинский В.П.

Как следует из предыдущего раздела, при выполнении операций с файлами данных ФС взаимодействует с ПВВ не непосредственно, а через дисковый КЭШ. Третьей подсистемой ОС, которая может непосредственно обращаться к ПВВ, является подсистема управления памятью. Если ФС обращается к ПВВ не через КЭШ, а напрямую (используя специальные файлы), то она пользуется услугами строковых драйверов. Строковый драйвер позволяет вышестоящим программам, то есть ФС при работе с файлами устройств, выполнять ввод-вывод строк байтов произвольной длины.

В отличие от строкового, блочный драйвер выполняет запросы дискового КЭШа или подсистемы управления памятью по вводувыводу блоков — последовательностей байтов фиксированной длины. Обычно длина блока равна длине сектора диска (512 байтов), умноженной на степень двойки. Например, для подсистемы управления памятью блок соответствует физической странице, длина которой может составлять 512*8 = 4096 байтов.

При рассмотрении дискового КЭШа в п. 6.4.2 нами был рассмотрен дескриптор элемента буфера КЭШа. Данный дескриптор содержит описание той работы по вводу-выводу блока, которую должна выполнить ПВВ по запросу КЭШа. Что касается самого этого запроса, то он содержит лишь указатель на соответствующий дескриптор элемента буфера КЭШа. Подсистема управления памятью для каждой физической страницы ОП записывает свой дескриптор со структурой, аналогичной структуре дескриптора элемента КЭШа. Для выполнения откачки (подкачки) физической страницы указатель на ее дескриптор передается в ПВВ.

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

вinode специального файла:

1)тип драйвера (строковый или блочный);

2)старший и младший номера устройства.

Таким образом, при обращении к ПВВ любая из вышестоящих подсистем (ФС, КЭШ, подсистема управления памятью или специальная ФС) использует для задания требуемого устройства пару чисел — старший (major) и младший (minor) номера устройства. Старший номер задает тип устройства, а младший номер определяет конкретное однотипное устройство. При этом в каче-

7. Подсистема ввода-вывода

235

стве устройства может выступать или устройство ввода-вывода, или отдельный дисковод, или раздел диска. В последнем случае младший номер устройства содержит в закодированном виде и номер дисковода, и номер раздела на диске.

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

КОММУТАТОР_СТРОЧНЫХ_ДРАЙВЕРОВ = {…, S k ,…} КОММУТАТОР_БЛОЧНЫХ_ДРАЙВЕРОВ = {…, Bk ,…},

где S k — совокупность точек входа для строчного драйвера со старшим номером k; Bk — совокупность точек входа для блочного драйвера со старшим номером k.

Для блочного драйвера запись Bk представляет собой структуру

Bk = {bko , bkc , bks , bki},

где bko — точка входа (адрес) интерфейсной процедуры драйвера «Открыть устройство» (каждый вызов этой процедуры приводит к созданию внутри драйвера нового экземпляра буфера, что позволяет драйверу выполнять одновременное обслуживание нескольких программных процессов. Для идентификации созданного буфера драйвер и вышестоящая программа могут использовать младший номер устройства); bkc — точка входа интерфейсной процедуры драйвера «Закрыть устройство»; bks — точка входа интерфейсной процедуры драйвера «Чтение-запись блока»; bki — точка входа интерфейсного модуля драйвера «Обработчик прерываний». На этот вход подается сигнал прерывания от устройства. Кроме того, данный вход можно использовать для программной имитации сигнала прерывания. Для этого достаточно сделать безусловный переход на адрес входа, предварительно поместив в стек адрес возврата из прерывания.

Каждому строчному драйверу соответствует своя запись Sk в коммутаторе строчных драйверов:

Sk = {sko , skc , skr ,skw , skp , ski},

где sko — точка входа (адрес) интерфейсной процедуры драйвера «Открыть устройство»; skc — точка входа интерфейсной процедуры

236

Одиноков В.В., Коцубинский В.П.

драйвера «Закрыть устройство»; skr — точка входа интерфейсной процедуры драйвера «Чтение с устройства»; skw — точка входа интерфейсной процедуры драйвера «Запись на устройство»; skp — точка входа интерфейсной процедуры драйвера «Опрос устройства» (данная процедура обычно используется для управления устройствами, не имеющими сигналов прерываний); ski — точка входа интерфейсного модуля драйвера «Обработчик прерываний». На этот вход подается сигнал прерывания от устройства.

7.2. Классификация драйверов

Деление драйверов на строковые и блоковые соответствует первому уровню классификации драйверов, приведенной на рис. 56. На втором уровне драйверы разделяются в зависимости от типа устройств, управляемых ими. При этом раличаются драйверы псевдоустройств, символьных и блочных устройств. Символьное устройство может выполнять только побайтовый обмен информацией с ОП. Примерами таких устройств являются клавиатура, экран, мышь и другие устройства ввода-вывода. Псевдоустройство имитирует работу реального устройства, например терминала (см. подразд. 3.1). Как символьное устройство, так и псевдоустройство позволяют реализовать лишь строковый верхний интерфейс драйвера.

Блочное устройство выполняет информационный обмен с ОП блоками фиксированной длины. К таким устройствам относятся практически все устройства ВП. Управление блочным устройством предоставляет для вышестоящих программ не только блочный, но и строковый верхний интерфейс. Услугами блочного верхнего интерфейса пользуются КЭШ и подсистема управления памятью, а услугами строкового верхнего интерфейса — ФС при выполнении запросов программ процессов по работе с файлами устройств.

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