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

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

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

Общая логика драйвера часов следует той же модели, что и для драйвера диска. Главная программа драйвера представляет собой бесконечный цикл, в котором сообщения принимаются, обрабатываются и отправляются ответные сообщения (кроме случая CLOCK TICK). Для обработки каждого типа сообщений предусмотрена отдельная процедура. Все эти процедуры, в соответствие со стандартным соглащением об именовании, имеют названия вида do xxx, где вместо ххх подставляется название действия. К сожалению, некоторые компоновщики усекают имена подпрограмм до семи или восьми символов, поэтому имена do set alarm и do set bme потенциально конфликтны. В силу чего выбрано название do setalarm. Подобная проблема иногда встречается в MINIX и решается обычно путем корректирования одного из имен.

Задача синхронного сигнального таймера

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

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

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



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

Обработчик прерываний часов

Как уже описывалось ранее, значение переменной realtime обновляется не сразу после возбуждения прерывания часов. Подпрофамма, обслуживающая прерывание, обновляет значение переменой pencHng ticks, а также выполняет некоторые дополнительные простые действия, такие как учет процессорного времени или же уменьшение значения счетчика кванта времени. Сообщение отправляется задаче таймера только в том случае, если требуются более сложные операции. Такое поведение является компромиссом между идеей о том, что задачи в MINIX должны взаимодействовать исключительно при помощи сообщений, и пониманием того, что на практике обработка каждого сигнала таймера потребляет процессорное время. Практика показала, что на медленных машинах переход от реализации, где сообщение отправляется задаче таймера по каждому прерыванию, к описанной выше реализации может привести к повышению производительности до 15 %.

Миллисекундные задержки

Как еще одна уступка реальности, в файле с1оск.с имеется несколько подпрофамм, которые позволяют задавать задержки с миллисекундным разрешением. Такие небольшие задержки необходимы для работы с некоторыми устройствами ввода/вывода. Реализовать их при помощи таймеров и механизма передачи сигналов практически невозможно. Находящиеся в этом файле функции должны вызываться задачей напрямую. В их основе старейший и простейший механизм: непрерывный опрос. Непрерывно, с максимально возможной скоростью считывается значение счетчика, используемого для генерации прерываний, и считанное значение преобразуется в миллисекунды. Это делается до тех пор, пока не истечет требуемое время.

Резюме

Таблица 3.8 резюмирует различные сервисы, предоставляемые кодом в файле clock.c. Существует несколько путей доступа к таймеру и несколько вариантов выполнения запроса. Некоторые из сервисов доступны для любого процесса, эти сервисы возвращают результат выполнения запроса при помощи сообщения.

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



дуры ожидания вызовы milli elapsed, например, во время ожидания при считывании данных из порта.

Таблица 3.8. Сервисы, предоставляемые программным обеспечением таймера

Сервис

Способ доступа

Ответ

Клиенты

Gettime

Системный вызов

Сообщение

Любой процесс

Uptime

Системный вызов

Сообщение

Любой процесс

Uptime

Вызов функции

Значение, возвращенное функцией

Ядро или задача

Alarm

Системный вызов

Сигнал

Любой процесс

Alarm

Системный вызов

Активизация сторожевой функции

Задача

Synchronous alarm

Системный вызов

Сообщение

Сервер

Milli delay

Вызов функции

Активное ожидание

Ядро или задача

Milli elapsed

Вызов функции

Значение, возвращенное функцией

Ядро или задача

3.8.4. Реализация драйвера часов в MINIX

При запуске MINIX вызываются все имеющиеся в системе драйверы. Больщин-ство из них просто делают попытку получить сообщение и блокируются. Драйвер часов, clock task, также делает такой вызов, но перед этим он вызывает подпрограмму init clock, настраивая профаммируемый таймер на работу с частотой 60 Гц. Когда драйвер получает какое бы то ни было сообщение, он прежде всего добавляет значение pending ticks к переменной realtime и сбрасывает переменную pending ticks. Это действие потенциально конфликтно с прерыванием таймера, поэтому оно обрамлено вызовами lock и unlock, предотвращающими возможную ситуацию состязания. Главный цикл у драйвера часов точно тот же, что и остальных драйверов: принимается сообщение, вызывается обслуживающая его функция и генерируется ответное сообщение.

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



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.
Копирование материалов разрешено исключительно при условии цититирования.