Разработка ядра Linux | страница 80



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

Определение необходимого системного вызова

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

Для аппаратной платформы x86 номер системного вызова сохраняется в регистре процессора >eax перед тем, как вызывается программное прерывание. Обработчик системных вызовов после этого считывает это значение из регистра >eax. Для других аппаратных платформ выполняется нечто аналогичное.

Функция >system_call() проверяет правильность переданного номера системного вызова путем сравнения его со значением постоянной >NR_syscalls. Если значение номера больше или равно значению >NR_syscalls, то функция возвращает значение >-ENOSYS. В противном случае вызывается соответствующий системный вызов следующим образом:

>call *sys_call_table(,%eax,4)

Так как каждый элемент таблицы системных вызовов имеет длину 32 бит (4 байт), то ядро умножает данный номер системного вызова на 4 для получения нужной позиции в таблице системных вызовов (рис. 5.2).

Рис. 5.2. Запуск обработчика системных вызовов и выполнение системного вызова

Передача параметров

В дополнение к номеру вызова, большинство системных вызовов требует передачи им одного или нескольких параметров. Во время перехвата исключительной ситуации пространство пользователя должно каким-либо образом передать ядру эти параметры. Самый простой способ осуществить такую передачу — это сделать по аналогии с передачей номера системной функции: параметры хранятся в регистрах процессора. Для аппаратной платформы x86 регистры >ebx, >ecx, >edx, >esi, >edi содержат соответственно первые пять аргументов. В случае редких ситуаций с шестью или более аргументами, используется один регистр, который содержит указатель на память пространства пользователя, где хранятся все параметры.

Возвращаемое значение также передается в пространство пользователя через регистр. Для аппаратной платформа x86 оно хранится в регистре >eax.

Реализация системных вызовов

Реализация системного вызова в ОС Linux не связана с поведением обработчика системных вызовов. Добавление нового системного вызова в операционной системе Linux является сравнительно простым делом. Тяжелая работа связана с разработкой и реализацией самого системного вызова. Регистрация его в ядре проста. Давайте рассмотрим шаги, которые необходимо предпринять, чтобы написать новый системный вызов в операционной системе Linux.