Учебная деятельность    

Операционные системы

Самостоятельная работа №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.

Задание

  1. В соответствии с приведенными выше заготовками реализовать библиотечный модуль, обеспечивающий работу с очередью готовых процессов, учитывая динамическое выделение памяти под процессы.
  2. Составить пример, иллюстрирующий работу библиотечного модуля.
  3. Отчет должен содержать тексты программ библиотечного модуля и примера.