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

10.3.6 Драйвер косвенного терминала

Зачастую процессам необходимо прочитать ил записать данные непосредственно на операторский терминал, хотя стандартный ввод и вывод могут быть переназначены в другие файлы. Например, shell может посылать срочные сообщения непосредственно на терминал, несмотря на то, что его стандартный файл вывода и стандартный файл ошибок, возможно, переназначены в другое место. В версиях системы UNIX поддерживается 'косвенный' доступ к терминалу через файл устройства '/dev/tty', в котором для каждого процесса определен управляющий (операторский) терминал. Пользователи, прошедшие регистрацию на отдельных терминалах, могут обращаться к файлу '/dev/tty', но они получат доступ к разным терминалам.

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

10.3.7 Вход в систему

Как показано в главе 7, процесс начальной загрузки, имеющий номер 1, выполняет бесконечный цикл чтения из файла '/etc/inittab' инструкций о том, что нужно делать, если загружаемая система определена как 'однопользовательская' или 'многопользовательская'. В многопользовательском режиме самой первой обязанностью процесса начальной загрузки является предоставление пользователям возможности регистрироваться в системе с терминалов (Рисунок 10.19). Он порождает процессы, именуемые getty-процессами (от 'get tty' — получить терминал), и следит за тем, какой из процессов открывает какой терминал; каждый getty-процесс устанавливает свою группу процессов, используя вызов системной функции setpgrp, открывает отдельную терминальную линию и обычно приостанавливается во время выполнения функции open до тех пор, пока машина не получит аппаратную связь с терминалом. Когда функция open возвращает управление, getty-процесс исполняет программу login (регистрации в системе), которая требует от пользователей, чтобы они идентифицировали себя указанием регистрационного имени и пароля. Если пользователь зарегистрировался успешно, программа login наконец запускает командный процессор shell и пользователь приступает к работе. Этот вызов shell'а именуется 'login shell' (регистрационный shell, регистрационный интерпретатор команд). Процесс, связанный с shell'ом, имеет тот же идентификатор, что и начальный getty-процесс, поэтому login shell является процессом, возглавляющим группу процессов. Если пользователь не смог успешно зарегистрироваться, программа регистрации завершается через определенный промежуток времени, закрывая открытую терминальную линию, а процесс начальной загрузки порождает для этой линии следующий getty-процесс. Процесс начальной загрузки делает паузу до получения сигнала об окончании порожденного ранее процесса. После возобновления работы он выясняет, был ли прекративший существование процесс регистрационным shell'ом и если это так, порождает еще один getty-процесс, открывающий терминал, вместо прекратившего существование.

алгоритм login /* процедура регистрации */

{

 исполняется getty-процесс: установить группу процессов (вызов функции setpgrp);

 открыть терминальную линию; /* приостанов до завершения открытия */

 if (открытие завершилось успешно) {

  исполнить программу регистрации: запросить имя пользователя;

  отключить эхо-сопровождение, запросить пароль;

  if (регистрация прошла успешно) { /* найден соответствующий пароль в /etc/passwd */

   перевести терминал в канонический режим (ioctl);

   исполнить shell;

  }

  в противном случае считать количество попыток регистрации, пытаться зарегистрироваться снова до достижения определенной точки;

 }

}

Рисунок 10.19. Алгоритм регистрации

10.4 ПОТОКИ

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

Ричи недавно разработал схему, получившую название 'потоки' (streams), для повышения модульности и гибкости подсистемы управления вводом- выводом. Нижеследующее описание основывается на его работе [Ritchie 84b], хотя реализация этой схемы в версии V слегка отличается. Поток представляет собой полнодуплексную связь между процессом и драйвером устройства. Он состоит из совокупности линейно связанных между собой пар очередей, каждая из которых (пара) включает одну очередь для ввода и другую — для вывода. Когда процесс записывает данные в поток, ядро посылает данные в очереди для вывода; когда драйвер устройства получает входные данные, он пересылает их в очереди для ввода к процессу, производящему чтение. Очереди обмениваются сообщениями с соседними очередями, используя четко определенный интерфейс. Каждая пара очередей связана с одним из модулей ядра, таким как драйвер, строковый интерфейс или протокол, и модули ядра работают с данными, прошедшими через соответствующие очереди.

Каждая очередь представляет собой структуру данных, состоящую из следующих элементов:

• процедуры открытия, вызываемой во время выполнения системной функции open

• процедуры закрытия, вызываемой во время выполнения системной функции close

• процедуры 'вывода', вызываемой для передачи сообщения в очередь

• процедуры 'обслуживания', вызываемой, когда очередь запланирована к исполнению

• указателя на следующую очередь в потоке

• указателя на список сообщений, ожидающих обслуживания

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

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

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

Рисунок 10.20. Поток после открытия

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

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату