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