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

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

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

Терминальный ввод

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

Когда пользователь входит с системной консоли, для него создается оболочка, которая для ввода, вывода и вывода ошибок использует /dev/console. Запустившись, оболочка пытается считать данные из стандартного ввода при помощи библиотечного вызова read. Эта процедура отправляет файловой системе сообщение, содержащее дескриптор файла, адрес буфера и количество считываемых байтов. На рис. 3.24 это сообщение обозначено как 1. Отправив сообщение, оболочка блокируется, ожидая ответа. (Пользовательские процессы исполняют только примитив send rec, который комбинирует вызов send с вызовом receive от того процесса, которому было послано сообщение.)

Файловая система получает сообщение и определяет местонахождение г-узла, соответствующего указанному дескриптору файла. В данном случае это i-узел для специального символьного файла /dev/console, содержащий младший и старший номера устройства для терминала. Старший номер для терминалов равен 4, младший для консоли равен 0.

Файловая система при помощи карты устройств, dmap, определяет номер задачи терминала. Затем она отправляет выбранной задаче сообщение, которое на рис. 3.24 показано как 2. Обычно к этому моменту пользователь еще ничего не напечатал, и драйвер терминала не в состоянии выполнить запрос. Поэтому драйвер немедленно отправляет файловой системе ответ, чтобы разблокировать ее и сообщить, что ни одного символа пока не введено. Это показано на рисунке как 3. Файловая система фиксирует в таблице tty table тот факт, что пользовательская задача ожидает ввода с терминала и переходит к следующему запросу. Пользовательская оболочка при этом остается заблокированной, пока не прибудут введенные символы.

Когда, наконец, на клавиатуре набран символ, возбуждаются два прерывания, одно - когда клавиша нажимается, и одно - когда отпускается. Это правило относится и к клавишам-модификаторам, таким как SHIFT или CTRL, которые сами по себе не передают символов, но все равно приводят к двум прерываниям. Прерыванию клавиатуры соответствует IRQ1, и ассемблерная функция hwint01 в файле mpx386.s вызывает функцию kbd hw int, которая, в свою очередь, вызывает scan keyboards, чтобы получить от аппаратного обеспечения клавиатуры коды клавиш. Если код соответствует обычному символу, он помещается во входную очередь клавиатуры, ibuf, тогда, когда прерывание было сгенерировано нажатием клавиши. Если прерывание инициировано отпусканием клавиши, оно в данном случае игнорируется. Коды клавиш-модификаторов, таких как CTRL или SHIFT, помещаются в очередь в любом случае, и при нажатии, и при отпускании. Обратите внимание: в очереди хранятся не ASCII-коды, а просто коды опросы кла-



виатуры, выдаваемые клавиатурами IBM. Затем kbd hwjnt устанавливает флаг tty events, являющийся частью клавиатурной секции tty table, вызывает force bmeouts и завершается.


Рис. 3.24. Запрос на чтение с терминала в отсутствие введенных символов. ФС - файловая система. TTY - задача терминала. Обработчик прерываний помещает в очередь введенные символы сразу же, но TTY пробуждается только обработчиком прерываний часов

В отличие от других обработчиков прерываний, kbd hwjnt не отправляет сообщений задаче терминала. Вызов force timeouts обозначен на рис. 3.24 пунктирными линиями (4). Это не сообщения. Здесь просто устанавливается значение переменной tty timeout, регистрирующее, что настало время вызвать функцию tty wakeup, которая и отправляет сообщение 5 задаче терминала. Обратите внимание, что, хотя код tty wakeup находится в файле tty.c, эта функция вызывается в ответ на прерывание часов. Таким образом, сообщение задаче терминала отправляет обработчик прерываний часов. Если данные вводятся быстро, в очереди может оказаться несколько символов, поэтому на рисунке изображены многократные вызовы force timeout.

Получив сообщение и пробудившись, задача терминала для каждого устройства проверяет значение флага tty events и для каждого устройства, у которого флаг установлен, вызывает handle events. Этот флаг может обозначать различные типы действий (хотя чаще всего - ввод), поэтому handle events как для ввода, так и для вывода всегда вызывает специфичные для данного устройства функции. При вводе с клавиатуры вызывается kb read, которая отслеживает наличие кодов управляющих клавиш CTRL, SHIFT и ALT и преобразует клавиатурные коды в ASCII, учитывая специальные символы и значения различных флагов, включая флаги, обозначающие канонический режим. В результате символ по большинству просто добавляется во входную очередь клавиатуры в tty table, хотя некоторые коды, например BACKSPACE, могут приводить к другому эффекту.



Кроме того, обычно in proccess осуществляет эхо-отображение вводимых ASCII-символов.

Когда введено достаточное количество символов, задача терминала вызывает ассемблерную подпрограмму phys copy, которая копирует введенные данные по адресу, указанному оболочкой. Эта операция также не является передачей сообщения, поэтому обозначена на рис. 3.24 пунктирной линией. На рисунке изображено несколько линий потому, что до того как пользовательский запрос будет полностью выполнен, данные могут быть переданы несколько раз. Когда операция полностью заверщится, драйвер терминала отправляет файловой системе сообщение о том, что работа выполнена (7), а файловая система в результате отправляет сообщение оболочке и выводит ее из состояния блокировки (8).

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

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

При работе с терминалом кэширование не имеет смысла. Кроме того, запрос файловой системы к драйверу диска всегда может быть обслужен максимум за несколько сотен миллисекунд, поэтому нет большой проблемы в том, что файловая система немного подождет. Операции с терминалом могут длиться часами или вообще могут не завершиться (в каноническом режиме драйвер ждет ввода полной строки, а в неканоническом ждет достаточно длинной строки, в зависимости от параметров MIN и TIME). Поэтому файловая система не должна блокироваться, ожидая выполнения запросов терминального ввода/вывода.

Вполне ожидаемо, что пользователь ввел какой-либо текст заранее, и символы благодаря предыдущим событиям 4 и 5 оказались доступны до того, как они были запрошены. В этом случае все события 1, 2, б, 7 и 8 происходят сразу же после запроса, а 3 вообще не происходит.

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



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