Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие 3000377.doc
Скачиваний:
29
Добавлен:
30.04.2022
Размер:
2.52 Mб
Скачать

Функция модуля service

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

Алгоритм работы функции service показан на рис. .12.

Рис.12 Алгоритм работы функции service.

Структура сообщения

Данные между модулями потока передаются посредством сообщений. Когда процесс передает данные устройству с помощью системного вызова write или putmsg, ядро системы формирует сообщение, которое последовательно передается от модуля к модулю, вплоть до драйвера. При этом каждый модуль может изменять, наращивать или сокращать сообщение, в соответствии с логикой своей работы.

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

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

Сообщения могут буферизироваться в очередях модулей. Сообщения в очередях описываются двумя структурами данных: msgb – заголовок сообщения и datab – заголовок блока данных.

Структура заголовка сообщения определена следующим образом:

struct msgb { // указатель на следующее сообщение в очереди struct msgb* b_next; // указатель на предыдущее сообщение в очереди struct msgb* b_prev; // указатель на связанное сообщение struct msgb* b_cont; // первая позиция для чтения из буфера сообщения unsigned char* b_rptr; // первая позиция для записи в буфер сообщения unsigned char* b_wptr; // указатель на описатель буфера сообщения struct datab* b_datap; };

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

struct datab { // адрес начала буфера unsigned char* db_base; // адрес первого байта за концом буфера unsigned char* db_lim; // счетчик ссылок на блок данных unsigned char db_ref; // тип сообщения unsigned char db_type; };

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

Сообщения связываются в двусвязный список через поля b_next, b_prev структуры msgb, как показано на рис. .13.

Рис.13. Общая структура списка сообщений

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

Поэтому необходим универсальный механизм, позволяющий связать с сообщением дополнительный объем данных. Заметим, что нельзя рассчитывать на возможность увеличения объема выделенной памяти за счет простого смещения конца буфера (за счет модификации поля db_lim в заголовке блока данных), т.к. неизвестно, как выполнялось распределения памяти и есть ли свободное место за текущим буфером.

Увеличение размера области данных сообщения выполняется при необходимости за счет создания нового сообщения, связанного с существующим сообщением через поле b_cont структуры msgb. Новое сообщение ссылается на новый заголовок блока данных, который адресует новый блок данных, как показано на рис. .13.