среда, 28 августа 2013 г.

PhantomEx: Эксперимент в отладчике - работа системных вызовов

Без этой статьи изложение принципов работы системных вызовов было бы не полным - думаю, читателю интересно будет взглянуть, что происходит "под капотом" ядра ОС, когда выполняется подобный запрос и как происходит взаимодействие кода ядра и кода прикладного потока.

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



Поставим точку останова на системный вызов чтения буфера клавиатуры в пользовательском потоке

Перед выполнением системного вызова - пользовательский режим
Заходим внутрь системного вызова (F5) и видим такую картину

Выполнение функции описанной через макроопределение
Мы находимся на макроопределении тела функции системного вызова, то есть непосредственно перед выполнением им программного прерывания INT 50h. При выполнении прерывания, через шлюз ловушки, мы оказываемся в режиме ядра

Выполнение прерывания INT 50h - переход в нулевое кольцо
Здесь управление передается в обработчик прерывания, мы находимся в ассемблерной обертке обработчика системного вызова. Переходим в сам обработчик

Обработчик системного вызова. Передача параметров через регистры
Тут мы видим, что переданные параметры: номер системной функции - 0, и это функция in_byte() определенная в таблице именно под номером 0; номер порта, чтение которого будем осуществлять находится в регистре EBX. Далее происходит чтение нужной функции из таблицы по её номеру

Чтение системной функции из таблицы
Убеждаемся что прочитан верный указатель на нужную нам функцию. Выполняем эту функцию, при этом переходим в ассемблерную функцию, осуществляющую интересующий нас вызов

Передача параметров и вызов функции in_byte()
Параметры, находящиеся в РОН передаются функции C через стек, и далее выполняется вызов данной функции

Работа системной функции - непосредственно обращение к буферу клавиатуры
Тут выполняется вызов функции in_byte() и чтение буфера клавиатуры. Прочитанное значение соответствует отпущенной клавише Enter - именно её мы нажимали, выбирая ядро в списке меню GRUB2. После возврата из системного вызова мы снова в пользовательском режиме

Возврат в режим пользователя





Примерно так происходят системные вызовы и в больших "взрослых" ОС, и теперь этот механизм имеется и в нашей, "игрушечной" системе.

Заключение


Данная статья - последняя в учебном цикле. Основные принципы организации работы ядра многозадачной ОС мы рассмотрели, причем довольно подробно. Дальше... дальше система станет такой, какой Вы сами захотите её сделать.

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