Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
UchbnoePosobieV14 - p2.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
2.08 Mб
Скачать

5.3.Многозадачная система с принудительной заменой контекста

Нужно обладать большим воображением, чтобы найти область практического применения для представленной в предыдущем разделе многозадачной надстройки. Видимо, больше возможностей в этом плане может быть у системы с принудительной заменой контекста. Очевидно, что функция Создание нового процесса, назначение которой выделение памяти под контекст и записи в него адреса начала процесса, может быть написана в том формате. Такой же вывод в отношении функции Переключатель контекста не так очевиден, так как при асинхронном замещении контекста возникают проблемы с запоминанием точки «замораживания» процесса, отдающего управление системой. Немного подумав, можно придти к выводу, что единственная возможность принудительного переключения процесса – это осуществить её из обработчика аппаратного прерывания (чаще всего из обработчика прерывания по таймеру), что требует существенной перестройки процедуры переключения контекста. В действительности эту функцию, разработанную для оболочки с синхронной заменой контекста, в том же формате можно применить для принудительного замещения контекста. Разберёмся в этой ситуации подробнее.

В однопроцессорной системе в конце каждого тика таймером инициализируется аппаратное прерывание. В начале обработчика прерывания запоминаются в специальном системном стеке значения регистров, совокупностью которых вполне определяется контекст выполняемой задачи в точке «замораживания». Далее изменяется показание часов, восстанавливаются прежние значения регистров и управление обратно передается процессу (Рис. 5 .15а).

Рис. 5.15. Использование процессорного времени при запоминании контекста

Допустим, что удалось перестроить обработчик прерывания по таймеру таким образом, что в момент аппаратного прерывания Процесса 1 (см. Рис. 5 .15б) в нем вызы­вается макрос _Trancfer macro des1,des2, который в синхронной оболочке переклю­чал бы с Процесса 1 на Процесс 2. Если Процесс 2 вызывается в первый раз, то он начнет выполняться сначала. Отличие от работы этого переключателя в синхронной оболочке заключается в запоминании точки в обработчике прерывания – Контекст 1(в des1). Если обработчик работал бы в штатном режиме, то из этой точки управление системой вернулось бы первому процессу. Чтобы из обработчика преры­ва­­ния попасть в первый процесс, следует восстановить контекст, на который указыва­­ет des1. Говоря другими словами, достаточно запомнить соответствующую точку обра­ботчика прерывания, что может быть осуществлено уже разработанным переключателем.

Таким образом, оболочку с асинхронной заменой контекста можно создать на основе оболочки с синхронной заменой, дополнив последнюю:

    • функцией Запуск диспетчера;

    • функцией Остановка диспетчера;

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

Запуск диспетчера. Эта функция связывает новый обработчик с аппаратным прерыванием по таймеру и переключает управление на первый процесс. Новый обработчик прерывания наряду с организацией переключения контекстов должен выполнять функции стандартного обработчика, связанные с изменением показания часов. В общем случае Запуск диспетчера состоит из 4-х операций:

    • запомнить прежнее значение обработчика, например, прерывания 61h ;

    • переключить прежний обработчик прерывания по таймеру на уровень 61h;

    • новый обработчик связать с прерыванием по таймеру;

    • переключить управление на первый процесс.

Первая операция является «данью корректности» – свободное прерывание 61h может быть уже использовано для некоторых целей, и после окончания работы надстройки целесообразно вернуться в исходное состояние. Вторая операция позволяет вызовом программы обработки прерывания int 61h из нового обработчика решить проблему с коррекцией текущего времени.

Остановка диспетчера. Если функция Запуск диспетчера запускает многозадачную надстройку, то процедура Остановка диспетчера осуществляет возвращение в однозадачную систему. Для этого достаточно процвести 3 операции:

    • возвратить прежнее значение адреса на уровень 61h;

    • возвратить прежнее значение адреса на уровень 08h;

    • переключить управление в контекст основной программы.

Новый обработчик. Новый обработчик прерывания по таймеру должен:

    • быть приемников прежнего обработчика и исправно изменять показания часов;

    • организовать последовательное переключение процессов.

Выполнение первой функция, как уже указывалось, осуществляется командой int 61h.

Вторую функцию можно реализовать несколькими способами. В данном варианте она строится на основе глобального счетчика и таблицы переходов, на основе которой, кстати, сконструирован в языке СИ оператор switch. Свойства таблицы переходов позволяют осуществлять переключение для любого количества вариантов одинаково быстро (см. далее текст программы). Схема переключения производится следующим образом:

    • при входе в обработчик прерывания значения глобального счетчика увеличивается на единицу;

    • полученное значение делится на число процессов и остаток от деления определяет вариант выбора;

    • по номеру варианта из таблицы переходов определяется коды, обрабатывающие этот вариант.

Такое переключение требует описания в обработчике прерывания всех вариантов, что увеличивает его объём. Однако, скорость обработки практически такая же, как и при одном варианте.

Использование очередей (см. дальше) позволяет в этой ситуации обойтись более коротким кодом.

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

;*******************************************************************

; Пример программы для многозадачной надстройки с асинхронной заменой контекста

;( принудительное ЗАМЕЩЕНИЕ КОНТЕКСТА)

;*******************************************************************

include macro.lib ;текст макроса не изменился

st1 segment stack

db 100h dup (?)

st1 ends

dan segment public

;****************************************************************

; <выделяется память под стеки и дескрипторы>

;****************************************************************

num_pr dw 2 ;число прикладных программ

dan ends

cd_1 segment public

assume ss:st1,cs:cd_1,ds:dan

;*******************************************************************

extrn pr1: far ;прикладные программы объявляем

extrn pr2: far ;как внешние

;*******************************************************************

Trancfer proc far ;текст подпрограммы остался неизменным

;*******************************************************************

trancfer endp

;*******************************************************************

; запустить диспетчер

;*******************************************************************

set_disp proc far

;сохранение прежнего значения прерывания 08н

cli

mov ax,3508h

int 21h

mov _08_cs,es

mov _08_ip,bx

sti

;сохранение прежнего значения прерывания 61н

cli

mov ax,3561h

int 21h

mov _61_cs,es

mov _61_ip,bx

sti

;устанавливаем 08н прерывание на 61н

push ds

mov dx,_08_ip

mov ax,_08_cs

mov ds,ax

mov ax,2561h

int 21h

pop ds

;устанавливаем новый обработчик на 08н

push ds

mov dx,offset handler

mov ax,seg handler

mov ds,ax

mov ax,2508h

int 21h

; переключаем на прикладной процесс

_Trancfer cont_main,cont_1

pop ds

retf

set_disp endp

;------------------------------------------------------------------------

; остановить диспетчер

;--------------------------------------------------------------------------}

s_disp proc far

;восстанавливаем прежний обработчик на 08н

cli

push ds

mov dx,_08_ip

mov ax,_08_cs

mov ds,ax

mov ax,2508h

int 21h

pop ds

sti

;восстанавливаем прежний обработчик на 61н

cli

push ds

mov dx,_61_ip

mov ax,_61_cs

mov ds,ax

mov ax,2561h

int 21h

_Trancfer cont_2,cont_main ; возвращаемся в основную программу

pop ds

retf

sti

s_disp endp

;------------------------------------------------------------------------

handler proc far

push ds

push ax

push dx

push si

mov ax,dan

mov ds,ax

int 61h

dec count1

; cmp count,7

; je @aa

; call s_disp

; jmp @b

@aa:

mov ax,count

mov dx,0

div num_pr

inc count

mov si,dx

shl si,1

jmp cs:jump_table[si]

jump_table dw foot1,foot2 ; таблица переходов

foot1:

_Trancfer cont_1,cont_2

jmp @b

foot2:

cmp count1,0

jnz @2

call s_disp

jmp @b

@2: _Trancfer cont_2,cont_1

@b:

mov al,20h ;сбрасываем через порт 20h контроллера

out 20h,al ;прерываний приоритет

;текущего прерывания (по таймеру)

pop si

pop dx

pop ax

pop ds

iret

handler endp

;*******************************************************************

main proc far ; программа ядра

begin:

mov ax,dan

mov ds,ax

;очистка экрана

;*******************************************************************

mov ax,0600h

mov bh,07h

mov cx,00h

mov dx,184fh

int 10h

;*******************************************************************

Newproc ar_1,cont_1,pr1 ;создание первого процесса

Newproc ar_2,cont_2,pr2 ;создание второго процесса

Newproc ar_g,cont_main,main ;создание главного процесса

call set_disp

mov ah,4ch

int 21h

main endp

cd_1 ends

end begin

;*******************************************************************

; Пример текста прикладной программы

; Прикладная программа теперь не содержит Переключателей контекста

;*******************************************************************

segment public

count1 dw 100h

d_1 ends

;****************************************************************

c_1 segment public

assume ds:d_1,cs:c_1

public pr1

; < ----тексты подпрограмм--------- >

pr1 proc far

; < ----текст основной подпрограммы--------- >

pr1 endp

c_1 ends

end

;*******************************************************************

;Аналогичным образом пишутся остальные прикладные программы, которые

;объединяются с системными функциями, обычными для ассемблера способами;

;*******************************************************************

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]