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

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

Последняя строка в цикле вызывает функцию in transfer в том случае, если только что помещенный в очередь символ привел к ее заполнению. В обычных условиях, в которых протекает действие, in transfer ничего бы не сделала, поскольку значение tp->tty eotct равно нулю, tp->tty m1n - единице (предполагается, что очередь обслуживалась нормально и предшествующий ввод был принят после завершения строки), и последняя проверка привела бы к немедленному возврату.

Итак, рассмотрев работу in transfer для обычного символа в стандартных условиях, мы вновь вернемся к нашему началу, но теперь взглянем, что происходит в менее обыденной ситуации. Первым будет на рассмотрении символ escape, который позволяет символам, в обычной ситуации имеющим специальное значение, передаваться пользовательскому процессу. Действие этого символа включается установкой флага tp->tty escaped. Когда ESC-режим активен, флаг сбрасывается, а к текущему символу добавляется бит IN ESC, на рис. 3.27 обозначенный как V. Это вызывает дополнительную обработку при выводе эха символа на экран; чтобы сделать такие символы видимыми, они отображаются как плюс сам символ. Кроме того, бит IN ESC предотвращает интерпретацию символа как специального. Следующие несколько строк проверяют сам ESC-символ, LNEXT (по умолчанию CTRL+V). При его обнаружении устанавливается флаг tp->tty escaped и дважды вызывается rawecho, чтобы вывести и примыкающий символ забоя. Это напоминает пользователю, что действует ESC-режим, а последующий ввод затирает Символ LNEXT - пример символа, влияющего на обработку последующего ввода (в данном случае затрагивается только один последующий символ). Такой символ не заносится в очередь, и после двух вызовов rawecho цикл переходит в начало. Порядок указанных двух проверок важен, так как им обеспечивается возможность передать LNEXT пользовательскому процессу. Для этого символ необходимо ввести дважды.

Следующий специальный символ, обрабатываемый in process, - это REPRINT (CTRL+R). Обнаружение этого символа инициирует вызов reprint, что приводит к повторному отображению выведенного эха. В дальнейшем сам символ REPRINT игнорируется и не оказывает влияния на входную очередь.

Изучать, как обрабатываются все остальные специальные символы, было бы утомительно, а исходные коды функции in process достаточно прямолинейны. Поэтому мы упомянем лишь еще несколько деталей. Во-первых, использование специальных битов из старшего байта 16-разрядного значения во входной очереди позволяет легко разбивать символы на классы, имеющие сходный эффект. Так, все символы EOT (CTRL+D), LF и альтернативный символ EOL (по умолчанию не задан) отмечаются битом EOT, на рис. 3.27 это бит D, что позволяет их легко распознавать. Наконец, мы объясним странное поведение in transfer, описанное ранее. Ответное сообщение не генерируется каждый раз при завершении функции, хотя, казалось бы, после вызова in transfer всегда следует код, генерирующий ответ. Вспомните, что вызов in transfer, делаемый в in process, когда очередь полна, не имеет эффекта в каноническом режиме. Но если требуется неканоническая обработка, каждый символ помечается битом EOT, и, таким образом, tp-> tty eotct подсчитывает все символы. В свою очередь, это приводит к переходу



в главный цикл in transfer при ее вызове, когда вызов делается по причине заполнения очереди в неканоническом режиме. В таком случае не нужно после возврата из in transfer передавать задаче терминала никаких сообщений, ведь после этого наверняка будут считаны еще символы. Конечно, хотя в неканоническом режиме отдельный вызов read офаничен размером входной очереди (в MINIX - 255 символов), в неканоническом режиме read должна быть способна передать количество символов по POSIX, задаваемое константой POSIX SSIZE.MAX. В MINIX это значение равно 3267.

Несколько следующих функций из tty.c обеспечивают поддержку ввода символов. Функция echo особым образом обрабатывает некоторые символы, но боль-щинство из них просто отображаются ею на выводе того терминала, который используется для ввода. Когда вывод от пользовательского процесса направлен на устройство, может оказаться, что в этот момент на устройство производится эхо-отображение. Когда пользователь попытается удалить последний введенный символ, это усложнит дело. Чтобы решить проблему когда производится обычный вывод, флаг tp->tty reprint всегда устанавливается аппаратно-зависимыми функциями вывода. Поэтому функция, которая вызывается для обработки символа забоя, может сообщить, что к экрану применен смешанный вывод. Поскольку в echo для вывода символов также привлекаются аппаратные процедуры вывода, текущее значение флага tp->tty reprint сохраняется в локальной переменной гр и восстанавливается после вывода. Исключение составляет случай, когда только что начался ввод новой строки. Здесь переменной гр присваивается значение FALSE, тем самым обеспечивается, что флаг tp->tty reprint будет сброшен по завершении выполнения echo.

Вы могли заметить, что функция echo возвращает значение. Например, вы могли встретить такую запись в коде in process:

ch echo(tp, ch):

Возвращаемое значение говорит о том, сколько знакомест занял на экране вывод, и может достигать восьми в случае символа TAB. Эти символы подсчиты-ваются в поле, которое на рис. 3.27 обозначено как сссс. Обычные символы занимают одно знакоместо, но специальные (за исключением TAB, CR, NL или DEL (Ox7F)) требуют два, они отображаются как и печатный ASCII-символ. С другой стороны, NL или CR занимают ноль знакомест. Конечно же, сам вывод эха должен осуществляться при помощи аппаратно-зависимых подпрограмм, и когда устройству нужно передать символ, делается косвенный вызов подпрофаммы, адрес которой хранится в tp->tty echo, как делается, например, для обычных символов.

Следующая функция, rawecho, вызывается тогда, когда необходимо обойти специальную обработку, присущую echo. Она проверяет, установлен ли флаг ECHO, и если да, отправляет введенный символ аппаратно-зависимой подпрофамме tp->tty echo без всякой дополнительной обработки. Локальная переменная гр используется для того, чтобы сохранить значение флага tp->tty reprint.

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



лить из нее последний введенный символ, то есть если очередь не пуста и последний символ не является переносом строки. Здесь проверяется значение флага tp->tty reprint, упоминавшегося при обсуждении функции echo и rawecho. Когда этот флаг равен TRUE, это влечет вызов reprint, чтобы показать на экране чистую копию редактируемой строки. Чтобы узнать, сколько знакомест необходимо очистить, проверяется значение поля len у последнего введенного символа (на рис. 3.27 это поле сссс), и для каждого знакоместа при помощи rawecho выводится последовательность забой-пробел-забой , стирающая символ с экрана.

Следующая функция имеет имя reprint. В дополнение к тому, что ее вызывает backover, она может вызываться, когда пользователь нажимает клавишу REPRINT (CTRL+R). Цикл в коде этой функции сканирует входную очередь в обратном направлении до последнего разрыва строки . Если разрыв строки является последним введенным символом, значит, для функции нет поля деятельности, и она заканчивает работу. Если это не так, сначала функция выводит на экран символ CTRL+R, который отображается как *R , переходит на следующую строку и повторно показывает содержимое очереди, начиная с последнего символа разрыва строки до конца.

Вот теперь мы добрались до out process. Как и in process, она вызывает аппа-ратно-зависимые функции вывода, но устроена проще. Сама эта функция вызывается специфическими подпрограммами вывода, действующими при работе последовательного интерфейса RS-232 и псевдотерминала, но не требуется для подпрофамм консоли. Эта функция обрабатывает круговой байтовый буфер, но не удаляет из него символы. Единственное, что она меняет в массиве, - вставляет перед символами NL символы CR, если установлены биты OPOST (разрешение обработки вывода) и ONLCR (преобразование NL в CRLF) в поле tp->tty termios.oflag. В MINIX по умолчанию эти биты установлены. Работа функции заключается в поддержании значения переменной tp->tty position в структуре tty устройства. Усложняют жизнь символы табуляции и забоя.

Далее следует подпрофамма devJoctL Она поддерживает dojoctl, выполняя функции tcdrain и tcflush, когда dojoctl вызывается с аргументом TCSADRAIN и TCSAFLUSH. Вызов dojoctl не может немедленно начать выполнение в том случае, если вывод еще не завершен, поэтому информация о запросе сохраняется в полях структуры tty, зарезервированных для этой цели. Когда запустится handle events, она после вызова аппаратно-зависимой подпрограммы проверит значение флага tp->ttyJoreq, и если имеется отложенная операция, вызовет devJoctL Сама функция devjoctl проверяет tp->tty outleft, чтобы узнать, завершен ли вывод. Если это так, выполняются те же действия, которые dojoctl выполнила бы в варианте без задержки. При работе tcdrain единственное, что нужно сделать, - это сбросить поле tp->ttyJoreq и отправить ответное сообщение файловой системе с просьбой разбудить приостановленный процесс, сделавший вызов. Вариант TCSAFLUSH вызова tcsetaddr прибегает к ttyjcancel, чтобы прервать ввод. В обоих вариантах tcseatddr структура termios, адрес которой передается при вызове ioctl, копируется в поле tp->tty termios. Затем вызывается setattr и посылается ответное сообщение, как и в случае с tcdrain, с целью разблокировать процесс-инициатор вызова.



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