Главная страница  Межпроцессное взаимодействие (состязание) 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 [ 64 ] 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187

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

Для дисков ввод и вывод в основном сводятся к передаче устройству соответствующей команды и ожиданию ее заверщения. Большую часть работы выполняет контроллер диска, поэтому обработчик прерывания весьма прост. Мы видели, что весь код обработчика прерываний для жесткого диска умещается в три строки и содержит единственную операцию ввода/вывода, считывающую единственный байт, с целью определить состояние контроллера. Конечно, если бы все прерывания обрабатывались так просто, наша жизнь была бы намного легче.

Но иногда бывает нужно выполнять более сложные действия. Механизм передачи сообщений имеет свою цену. Когда прерывания происходят часто, а объем передаваемых данных невелик, имеет смысл усложнить обработчик и отложить передачу сообщения до следующего прерывания, чтобы дать обслуживающей устройство задаче больше времени. В MINIX таким путем обрабатываются прерывания от таймера. При обработке большинства сигналов от таймера основная задача - обновление значения системного времени. Это можно сделать и не прибегая к задаче таймера. Поэтому обработчик прерываний таймера, вместо того чтобы посылать сообщение, увеличивает значение переменной, названной pending ticks. Тогда текущее время рассчитывается как сумма времени, которое было записано при последнем выполнении задачи таймера, и значения в переменной pending ticks. Когда управление все-таки передается задаче таймера, она увеличивает системное время на величину pending ticks и обнуляет эту переменную. Обработчик прерывания таймера проверяет значения некоторых других переменных и передает сообщение задаче таймера только в том случае, если для нее есть реальная работа, например передача сигнала срабатывания таймера или планирование очередного процесса. Кроме того, может быть отправлено сообщение задаче терминала.

Рассматривая задачу терминала, мы видим еще одну вариацию на тему обработки прерываний. Эта задача обслуживает несколько различных типов устройств, включая клавиатуру и линии связи RS-232. Каждое из них имеет собственный обработчик прерываний. Клавиатура полностью соответствует описанию устройства, которое с каждым прерыванием выполняет очень малый объем ввода/вывода. На PC прерывание происходит каждый раз, когда нажимается или отпускается клавиша. Это относится и к специальным клавишам, таким как SHIFT или CTRL. Но если отбросить специальные клавиши, можно сказать, что с каждым прерыванием передается примерно половина символа. Так как с таким объемом информации задача терминала мало что может сделать путного, имеет смысл передавать сообщение только в том случае, если оно содержит законченную информацию. Детали мы рассмотрим позже, а сейчас скажем лишь, что обработчик



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

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

3.4.2. Драйверы устройств в MINIX

Для каждого из классов устройств ввода/вывода в MINIX существует отдельная задача (драйвер). Эти драйверы являются полноценными процессами, каждый со своим состоянием, регистрами, стеком и т. д. Друг с другом драйверы при необходимости взаимодействуют при помощи стандартного механизма передачи сообщений. Код простых драйверов собран в одном файле, например clock.c. Другие драйверы, такие как для RAM-диска, жесткого диска и дискет, имеют отдельные файлы с кодом для поддержки устройств каждого типа, а также набор общих подпрограмм в driver.c, необходимых для всех драйверов. Таким образом, уровень драйверов устройств на рис. 3.4 разбивается на два подуровня: аппаратно-зависимый и аппаратно-независимый. Такое разбиение упрощает адаптацию к различным конфигурациям оборудования. При этом, хотя используется довольно большое количество общего кода, драйвер каждого типа дисков работает как отдельная задача для поддержки быстрой передачи данных.

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

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

Основное различие между драйверами устройств и обычными процессами в том, что все драйверы скомпонованы в один файл и, таким образом, имеют об-



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

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

Ядро разбито на процессы

Монолитное ядро

Файловая система

Драйвер устройства


Пользовательские процессы

Пользовательская часть

Часть, работающая в ядре

Процесс


Часть, работающая в пространстве попьзователя


Стрелками 1-4 обозначены запросы и ответные сообщения между тремя независимыми процессами

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

Рис. 3.11. Два способа построения взаимодействия пользователя и системы: а - сообщения с запросами и ответами между тремя независимыми процессами; б - передача управления в адресное пространство ядра из адресного пространства пользователя по ловушке. Файловая система вызывает драйвер ядра как устройство. Вся операционная система есть часть каждого процесса

В UNIX у каждого процесса есть две части: одна в пространстве пользователя и другая в пространстве ядра, как показано на рис. 3.11, б. Когда процесс делает



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 [ 64 ] 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187

© 2000 - 2018 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.