Операционные системы
Самостоятельная работа №2
Исследование принципов реализации процессов и очередей многозадачного ядра
(вытесняющая многозадачность, принципы планирования процессов)
Цель работы: ознакомление с принципами реализации процессов и очередей в ядре многозадачной среды
Общие сведения
Реализация псевдопараллельного режима с помощью явного включения в пользовательские процессы оператора ПЕРЕДАТЬ_УПРАВЛЕНИЕ обладает недостатками:
- Пользовательские процессы включают в себя действия, которые по существу не относятся к их функциям;
- Интервалы процессорного времени, предоставляемые процессам, зависят от самих процессов и есть опасность захвата процессора на длительный срок одним процессом.
Поэтому в многозадачных системах используется принудительная передача управления. Моменты принудительной передачи управления определяются прерываниями от таймера. Такой способ передачи управления называется диспетчеризацией.
Работает многозадачная система с принудительной диспетчеризацией следующим образом.
Выполнение текущей сопрограммы приостанавливается прерыванием от таймера. Управление передается программе-обработчику прерывания. Обработчик выполняет действия по выбору следующей сопрограммы и передает управление ей оператором ПЕРЕДАТЬ_УПРАВЛЕНИЕ.
Таким образом каждой сопрограмме выделяется квант времени для выполнения.
Установка вектора прерывания в языке Pascal:
SetIntVec(IntNo : byte; Vector : pointer)где: IntNo – номер вектора прерывания; Vector – адрес процедуры-обработчика прерывания.
Чтение вектора прерывания в языке Pascal:
GetIntVec(IntNo : byte; Var Vector : pointer)где: IntNo – номер вектора прерывания; Vector – переменная, в которую пишется адрес процедуры-обработчика прерывания.
Примечание. Номер вектора прерывания от таймера – 8; номера свободных векторов для переустановки системного обработчика прерываний от таймера: 6016—6616; 7816—7F16.
Структура процедуры-обработчика прерывания:
Procedure Handler; interrupt; {обязательный атрибут} Begin ... End {Handler}.
Параллельно выполняемые в многозадачной среде процедуры называются процессами.
Поскольку процессор один, а процессов много, то появляется средство упорядочивания доступа процессов к процессору, принимающее форму очереди.
Важнейшим видом очереди является очередь процессов, готовых к выполнению.
Для обеспечения возможности включения процесса в очереди необходимо модифицировать дескриптор сопрограммы, реализующей процесс, введя в него поле – указатель на следующего.
С учетом возможности динамического создания и уничтожения представим процесс как объект следующего вида:
ПРОЦЕСС = ОБЪЕКТ {ДАННЫЕ:} ЭЛЕМЕНТЫ ДЕСКРИПТОРА СОПРОГРАММЫ; СЛЕДУЮЩИЙ; АДРЕС_СТЕКА; {МЕТОДЫ:} Procedure ИНИЦИАЛИЗИРОВАТЬ; Procedure ОСВОБОДИТЬ_ПАМЯТЬ; Procedure УСТАНОВИТЬ_СЛЕДУЮЩИЙ; Function ПОЛУЧИТЬ_СЛЕДУЮЩИЙ; КОНЕЦ;
Вторым видом объектов многозадачной среды является ОЧЕРЕДЬ, представляемая следующим описанием:
ОЧЕРЕДЬ = ОБЪЕКТ {ДАННЫЕ:} НАЧАЛО; {МЕТОДЫ:} Procedure ИНИЦИАЛИЗИРОВАТЬ; Procedure ОСВОБОДИТЬ_ПАМЯТЬ; Procedure ВКЛЮЧИТЬ_ПРОЦЕСС; Procedure ИСКЛЮЧИТЬ_ПРОЦЕСС; Function ПОЛУЧИТЬ_НАЧАЛО; КОНЕЦ;
В данной работе рассматривается очередь готовых процессов, которая может быть представлена как тип, производный от типа ОЧЕРЕДЬ:
ОЧЕРЕДЬ_ГОТОВЫХ = ОБЪЕКТ(ОЧЕРЕДЬ) {МЕТОДЫ:} Procedure ИНИЦИАЛИЗИРОВАТЬ; Procedure ОСВОБОДИТЬ_ПАМЯТЬ; Procedure ЗАПУСТИТЬ_ДИСПЕТЧЕР; Procedure ОСТАНОВИТЬ_ДИСПЕТЧЕР; Procedure ДОБАВИТЬ_НОВЫЙ_ПРОЦЕСС; Procedure АКТИВИЗИРОВАТЬ_СЛЕДУЮЩИЙ; КОНЕЦ;
Технология реализации процессов и очереди готовых процессов
Технология реализации процессов и очереди готовых процессов представлена в виде словесного описания библиотечного модуля, являющегося дальнейшим развитием предыдущей программы.
Unit DispObj; Interface Type ПРОЦЕСС = ОБЪЕКТ ЭЛЕМЕНТЫ ДЕСКРИПТОРА СОПРОГРАММЫ; СЛЕДУЮЩИЙ; АДРЕС_СТЕКА; Procedure ИНИЦИАЛИЗИРОВАТЬ; Procedure ОСВОБОДИТЬ_ПАМЯТЬ; Procedure УСТАНОВИТЬ_СЛЕДУЮЩИЙ; Function ПОЛУЧИТЬ_СЛЕДУЮЩИЙ; КОНЕЦ; ОЧЕРЕДЬ = ОБЪЕКТ НАЧАЛО; Procedure ИНИЦИАЛИЗИРОВАТЬ; Procedure ОСВОБОДИТЬ_ПАМЯТЬ; Procedure ВКЛЮЧИТЬ_ПРОЦЕСС; Procedure ИСКЛЮЧИТЬ_ПРОЦЕСС; Function ПОЛУЧИТЬ_НАЧАЛО; КОНЕЦ; ОЧЕРЕДЬ_ГОТОВЫХ = ОБЪЕКТ(ОЧЕРЕДЬ) Procedure ИНИЦИАЛИЗИРОВАТЬ; Procedure ОСВОБОДИТЬ_ПАМЯТЬ; Procedure ЗАПУСТИТЬ_ДИСПЕТЧЕР; Procedure ОСТАНОВИТЬ_ДИСПЕТЧЕР; Procedure ДОБАВИТЬ_НОВЫЙ_ПРОЦЕСС; Procedure АКТИВИЗИРОВАТЬ_СЛЕДУЮЩИЙ; КОНЕЦ; Var ReadyList : ОЧЕРЕДЬ_ГОТОВЫХ; Implementation Procedure ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ; Assembler; Asm ... End; Procedure РАЗРЕШИТЬ_ПРЕРЫВАНИЯ; Assembler; Asm ... End; Procedure СОЗДАТЬ_СОПРОГРАММУ; Begin ... End; Procedure ПЕРЕДАТЬ_УПРАВЛЕНИЕ; Assembler; Asm ... End; Procedure Handler; interrupt; Begin ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ; ReadyList.АКТИВИЗИРОВАТЬ_СЛЕДУЮЩИЙ; End; Procedure Idler; {всегда в очереди готовых} Begin while true do begin end; End; Procedure ПРОЦЕСС.ИНИЦИАЛИЗИРОВАТЬ; Begin СОЗДАТЬ_СОПРОГРАММУ; ЗАПОЛНИТЬ ПОЛЕ АДРЕС_СТЕКА; End; Procedure ПРОЦЕСС.ОСВОБОДИТЬ_ПАМЯТЬ; Begin ОСВОДИТЬ ПАМЯТЬ, ЗАНЯТУЮ ПОД СТЕК; End; Procedure ПРОЦЕСС.УСТАНОВИТЬ_СЛЕДУЮЩИЙ; Begin СЛЕДУЮЩИЙ := ... ; End; Function ПРОЦЕСС.ПОЛУЧИТЬ_СЛЕДУЮЩИЙ; Begin ПОЛУЧИТЬ_СЛЕДУЮЩИЙ := СЛЕДУЮЩИЙ; End; Procedure ОЧЕРЕДЬ.ИНИЦИАЛИЗИРОВАТЬ; Begin НАЧАЛО := NIL; End; Procedure ОЧЕРЕДЬ.ОСВОБОДИТЬ_ПАМЯТЬ; Begin {Цикл по всем процессам очереди} ПРОЦЕСС.ОСВОБОДИТЬ_ПАМЯТЬ; End; Procedure ОЧЕРЕДЬ.ВКЛЮЧИТЬ_ПРОЦЕСС; Begin ... End; Procedure ОЧЕРЕДЬ.ИСКЛЮЧИТЬ_ПРОЦЕСС; Begin ... End; Function ОЧЕРЕДЬ.ПОЛУЧИТЬ_НАЧАЛО; Begin ПОЛУЧИТЬ_НАЧАЛО := НАЧАЛО; End; Procedure ОЧЕРЕДЬ_ГОТОВЫХ.ИНИЦИАЛИЗИРОВАТЬ; Begin ОЧЕРЕДЬ.ИНИЦИАЛИЗИРОВАТЬ; End; Procedure ОЧЕРЕДЬ_ГОТОВЫХ.ОСВОБОДИТЬ_ПАМЯТЬ; Begin ОЧЕРЕДЬ.ОСВОБОДИТЬ_ПАМЯТЬ; End; Procedure ОЧЕРЕДЬ_ГОТОВЫХ.ЗАПУСТИТЬ_ДИСПЕТЧЕР; Begin ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ; ПЕРЕУСТАНОВИТЬ_ВЕКТОР_ПРЕРЫВАНИЯ_ОТ_ТАЙМЕРА; УСТАНОВИТЬ_НА_ВЕКТОР_8_ПРОЦЕДУРУ_Handler; ПОЛУЧИТЬ_НАЧАЛО; ИСКЛЮЧИТЬ_ПРОЦЕСС; ПЕРЕДАТЬ_УПРАВЛЕНИЕ; End; Procedure ОЧЕРЕДЬ_ГОТОВЫХ.ОСТАНОВИТЬ_ДИСПЕТЧЕР; Begin ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ; ВОССТАНОВИТЬ_ВЕКТОР_ПРЕРЫВАНИЯ_ОТ_ТАЙМЕРА; ПЕРЕДАТЬ_УПРАВЛЕНИЕ; {в главную программу} End; Procedure ОЧЕРЕДЬ_ГОТОВЫХ.ДОБАВИТЬ_НОВЫЙ_ПРОЦЕСС; Begin ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ; ПРОЦЕСС.ИНИЦИАЛИЗИРОВАТЬ; ВКЛЮЧИТЬ_ПРОЦЕСС; РАЗРЕШИТЬ_ПРЕРЫВАНИЯ; End; Procedure ОЧЕРЕДЬ_ГОТОВЫХ.АКТИВИЗИРОВАТЬ_СЛЕДУЮЩИЙ; Begin ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ; ВКЛЮЧИТЬ_ПРОЦЕСС; {текущий} ПОЛУЧИТЬ_НАЧАЛО; ИСКЛЮЧИТЬ_ПРОЦЕСС; ПЕРЕДАТЬ_УПРАВЛЕНИЕ; End; Begin ReadyList.ИНИЦИАЛИЗИРОВАТЬ; ReadyList.ДОБАВИТЬ_НОВЫЙ_ПРОЦЕСС;{Включение Idler} End.
С учетом приведенного библиотечного модуля пользовательская программа выглядит следующим образом:
Program User; Uses Disp; Procedure User_1; Begin while true do begin ... end; End; Procedure User_N; Begin while true do begin ... if УСЛОВИЕ then then begin {завершение выполнения} ReadyList.ОСТАНОВИТЬ_ДИСПЕТЧЕР; end; end; End; Begin ReadyList.ДОБАВИТЬ_НОВЫЙ_ПРОЦЕСС;{Включение User_1} ReadyList.ДОБАВИТЬ_НОВЫЙ_ПРОЦЕСС;{Включение User_N} ReadyList.ЗАПУСТИТЬ_ДИСПЕТЧЕР; End.
Задание
- В соответствии с приведенными выше заготовками реализовать библиотечный модуль, обеспечивающий работу с очередью готовых процессов, учитывая динамическое выделение памяти под процессы.
- Составить пример, иллюстрирующий работу библиотечного модуля.
- Отчет должен содержать тексты программ библиотечного модуля и примера.