Когда запускается процедура
Драйвер
Драйверы и модули очень похожи, они используют одинаковые структуры данных (streamtab
qinit
, module_info
) и одинаковый интерфейс (xx
open, xx
put, xx
service и xx
close). Однако между драйверами и модулями существуют различия.Во-первых, только драйверы могут непосредственно взаимодействовать с аппаратурой и отвечать за обработку аппаратных прерываний. Поэтому драйвер должен зарегистрировать в ядре соответствующий обработчик прерываний. Аппаратура обычно генерирует прерывания при получении данных. В ответ на это драйвер копирует данные от устройства, формирует сообщение и передает его вверх по потоку.
Во-вторых, к драйверу может быть подключено несколько потоков. Как уже обсуждалось, на мультиплексировании потоков построены многие подсистемы ядра, например, поддержка сетевых протоколов. В качестве мультиплексора может выступать только драйвер. Несмотря на то что драйвер в этом случае не является оконечным модулем (см., например, рис. 5.15), размещение драйверов существенным образом отличается от встраивания модулей.
Наконец, процесс инициализации драйверов и модулей различен. Функция
Головной модуль
Обработку системных вызовов процессов осуществляет головной модуль. Головной модуль потока является единственным местом, где возможно блокирование обработки и, соответственно, процесса, в контексте которого осуществляется операция ввода/вывода. Головной модуль является внешним интерфейсом потока, и хотя его структура похожа на структуру обычного модуля, функции обработки здесь обеспечиваются самой подсистемой STREAMS. В отличие от точек входа в модуль или драйвер потока, реализующих специфическую для данного устройства обработку, функции головного модуля выполняют ряд общих для всех потоков задач, включающих:
Трансляцию данных, передаваемых процессом с помощью системных вызовов, в сообщения и передачу их вниз по потоку.
Сообщение об ошибках и отправление сигналов процессам, связанным с потоком.
Распаковку сообщений, переданных вверх по потоку, и копирование данных в пространство ядра или задачи.
Процесс передает данные потоку с помощью системных вызовов
Системный вызов
#include
int putmsg(int fildes, const struct strbuf *ctlptr,
const struct strbuf* dataptr, int flags);
С помощью этого вызова головной модуль формирует сообщение, состоящее из управляющей части M_PROTO
M_DATA
. Содержимое сообщения передается с помощью указателей на структуру strbuf
— ctlptr
для управляющего блока и dataptr
для блоков данных.Структура strbuf
struct strbuf {
int maxlen;
int len;
void *buf;
}
где maxlen
len
— размер передаваемых данных, buf
— указатель на буфер.С помощью аргумента flags
RS_HIPRI
.В обоих случаях головной модуль формирует сообщение и с помощью функции