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

Буферизация в символьных драйверах

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

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

Часто процессы генерируют запросы ввода-вывода пакетами по несколько запросов, как показано на рис. .5.

Рис.5. Группировка запросов ввода-вывода

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

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

Рис.6. Буферизация запросов ввода-вывода

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

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

В UNIX системах символьным драйверам предоставляется стандартный механизм буферизации, основанный на структурах clist и cblock.

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

struct clist { // число символов в буфере int c_cc; // указатель на первый блок символов struct cblock* c_cf; // указатель на последний блок символов struct cblock* c_cl; };

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

Структура cblock определена следующим образом

struct cblock { // указатель на следующий блок данных struct cblock* c_next; // данные блока char c_data[CBSIZE]; };

Таким образом, используется структура буфера, показанная на рис. 7.

Рисунок 7. Структура буфера символьного драйвера

Если объем буферизированных данных растет, выделяются новые блоки cblock, при сокращении объема данных – высвобождающиеся блоки возвращаются системе.

Драйвер может создать экземпляр структуры clist, инициализировать его нулями и использовать системную поддержку символьной буферизации. Ядро предоставляет функции для работы с буфером, например putc(char, clist*) для записи символа в буфер или int getc(clist*) для чтения символа. При этом драйверу не надо заботиться о выделении или освобождении блоков, все эти операции автоматически выполняются ядром при добавлении удалении символов.