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

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

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

Сигналы, которые знает MINIX, определяются в файле /usr/include/signal.h, согласно стандарту POSIX. Они перечислены в табл. 4.4. В MINIX объявлены все требуемые POSIX сигналы, но пока что не все они поддерживаются. Например, стандартом определен набор сигналов для управления задачами, при помощи которых можно переводить задачу в фоновый режим и возвращать ее обратно. В MINIX не поддержано управление задачами, но программы, которые генерируют такие сигналы, могут быть перенесены под MINIX. Неподдерживаемые сигналы будут просто игнорироваться. Кроме того, MINIX определяет ряд сигналов, не имеющихся в POSIX, а также несколько синонимов для POSIX-имен, с целью обеспечить совместимость с более старым исходным кодом.

Сигналы генерируются либо ядром, либо при помощи системного вызова kill. Ядро MINIX всегда может генерировать сигналы SIGINT, SIGQUIT и SIGALARM, возможность генерировать другие сигналы зависит от аппаратной поддержки. Например, процессоры 8086 и 8088 не умеют обнаруживать недопустимые инструкции, а процессоры 286 и старше при попытке выполнить такую инструкцию уже вызывают прерывание. Это обусловлено возможностями аппаратного обеспечения. Чтобы в ответ на прерывание генерировать сигнал, разработчики операционной системы должны заготовить для этого код. В главе 2 мы видели, что в файле kernel/exception.с как раз содержится нужный код, для разных сочетаний условий. Таким образом, когда MINIX работает на машине с процессором 286 или старше, недопустимая инструкция приведет к появлению сигнала SIGKILL, но на компьютере с процессором 8088 такого никогда не произойдет.

То, что оборудование способно генерировать аппаратное прерывание при возникновении некоторой ситуации, не означает, что разработчики операционной системы могут во всем понадеяться на эту возможность. Так, все процессоры Intel, начиная с 286, распознают несколько типов нарушений целостности памяти, вызывающих исключения. Код в файле kernel/exception.h преобразует эти исключения в сигналы SIGSEGV.



Таблица 4.4. Сигналы MINIX, регламентированные POSlX. Знак (*) означает, что сигнал зависит от аппаратной поддержки, сигналы с пометкой (М) не исходят из POSIX и введены в MINIX для поддержания совместимости со старым кодом. В таблицу не попали несколько устаревших имен и синонимов

Сигнал

Описание

Источник

SIGHUP

Отбой

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

SIGINT

Прерывание

Ядро

SIGQUIT

Завершение

Ядро

SIGILL

Недопустимая инструкция

Ядро {*)

SIGTRAP

Прерывание трассировки

Ядро(М)

SIGABRT

Аномальное завершение

Ядро

SIGFPE

Ошибка при вычислениях с плавающей запятой

Ядро (*)

SIGKILL

Принудительное завершение (сигнал не может быть игнорирован или обработан)

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

SIGUSR1

Задаваемый пользователем сигнал № 1

Не поддерживается

SIGSEGV

Нарушение целостности памяти

Ядро (*)

SIGUSR2

Задаваемый пользователем сигнал № 2

Не поддерживается

SIGPIPE

Запись в канал, из которого никто не читает

Ядро

SIGALRM

Сигнал таймера, истечение тайм-аута

Ядро

SIGTERM

Сигнал завершения программы

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

SIGCHLD

Дочерний процесс завершил работу или остановился

Не поддерживается

SIGCONT

Продолжить работу после останова

Не поддерживается

SIGSTOP

Остановить выполнение процесса

Не поддерживается

SIGTSTP

Интерактивный сигнал останова

Не поддерживается

SIGTTIN

Фоновый процесс пытается выполнить ввод

Не поддерживается

SIGTTOU

Фоновый процесс пытается выполнить вывод

Не поддерживается

Нарушениям аппаратных границ стека и границ других сегментов соответствуют разные типы исключений, в расчете на различную их обработку. Тем не менее, в силу особенностей работы MINIX с памятью, не все возникающие нарушения могут быть обнаружены. Аппаратные регистры задают базовый адрес сегмента и его длину. В MINIX базовый адрес аппаратного сегмента стека совпадает с базовым адресом аппаратного сегмента данных, но аппаратно заданный размер сегмента данных превышает контролируемую программно границу. Другими словами, контролируемый аппаратно размер сегмента данных соответствует ситуации, когда стек уменьшился до нуля. Аналогично, заданный аппаратно объем стека соответствует нулевому объему данных. Таким образом, хотя некоторые из нарушений и поддаются аппаратному обнаружению, наиболее вероятная ошибка - повреждение области данных из-за переполнения стека - не де-



тактируется. Это следствие того, что с точки зрения аппаратных регистров и таблиц дескрипторов сегменты данных и стека пересекаются.

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

Где бы ни брали свое начало сигналы, менеджер памяти обрабатывает их одинаково. Сначала для каждого процесса-получателя делается набор проверок, с целью убедиться, можно ли передать ему сигнал. Один процесс может передавать другому сигнал в том случае, если первый принадлежит суперпользователю, либо если его эффективный UID равен реальному или эффективному UID второго. Но существует еще несколько условий, вмешивающихся в отправку сигнала. Например, нельзя передавать сигнал зомби. Также процессу нельзя передавать сигнал, если он явно сделал вызов sigaction, чтобы игнорировать возможный сигнал, или вызвал sigprocmask, чтобы его блокировать. Блокировка сигнала и пренебрежение им - разные вещи. Заблокированный сигнал запоминается и передается процессу, когда тот снимет блокировку (если он ее вообще снимет). Наконец, если у процесса-получателя недостаточно места в стеке, этот процесс принудительно завершается.

Когда все тесты пройдены, сигнал можно отправлять. Если процесс не сделал ничего, чтобы обработать сигнал, то и никакой информации передавать ему не требуется. В таком случае менеджер памяти выполняет обработку сигнала по умолчанию, обычно это означает либо завершение процесса, либо сброс дампа памяти в файл. Несколько сигналов по умолчанию игнорируются. Сигналы, которые в табл. 4.4 обозначены как не поддерживаемые, рекомендованы стандартом POSIX, но в MINIX игнорируются.

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



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