Главная страница Межпроцессное взаимодействие (состязание) цию о таймере удобно хранить в таблице процессов, выделяя под нее одно слово в каждой из записей. Для задач при срабатывании таймера должна вызываться некоторая функция, адрес которой должен где-то храниться. Для этой цели предназначен массив 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. Сервисы, предоставляемые программным обеспечением таймера
3.8.4. Реализация драйвера часов в MINIX При запуске MINIX вызываются все имеющиеся в системе драйверы. Больщин-ство из них просто делают попытку получить сообщение и блокируются. Драйвер часов, clock task, также делает такой вызов, но перед этим он вызывает подпрограмму init clock, настраивая профаммируемый таймер на работу с частотой 60 Гц. Когда драйвер получает какое бы то ни было сообщение, он прежде всего добавляет значение pending ticks к переменной realtime и сбрасывает переменную pending ticks. Это действие потенциально конфликтно с прерыванием таймера, поэтому оно обрамлено вызовами lock и unlock, предотвращающими возможную ситуацию состязания. Главный цикл у драйвера часов точно тот же, что и остальных драйверов: принимается сообщение, вызывается обслуживающая его функция и генерируется ответное сообщение. Функция do clocktick в действительности не вызывается при каждом сигнале таймера, как можно было бы подумать, глядя на ее название. Она вызывается тогда, когда обработчик прерываний определил, что необходимо выполнить некоторые важные действия. Сначала эта функция проверяет, не сработал ли таймер (сигнальный или сторожевой). Если это так, в таблице процессов просматриваются поля с информацией о запущенном таймере. За один проход по таблице может потребоваться обслужить несколько таймеров. Когда обнаруживается процесс, время срабатывания таймера у которого меньше текущего времени или равно ему, но не равно нулю, проверяется соответствующий этому процессу элемент массива watch dog. Если эта ячейка содержит адрес функции, значит, процесс затребовал сторожевой таймер, и функция вызывается. Для проверки значения указателя привлекается тот факт, что в языке С числовое значение одновременно может интерпретироваться и как логическое. Если в таблице watch dog обнаружен пустой указатель (в С ему соответствует нулевое значение.
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |