Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
os2.doc
Скачиваний:
0
Добавлен:
20.06.2023
Размер:
246.78 Кб
Скачать

2.3. Сопрограммы

Понятие «сопрограмма» не настолько широко известно, как «подпрограмма». Сопрограммы представляют собой средство моделирования и реализации параллелизма.

Суть сопрограмм лучше всего выявляется при их сопоставлении с процедурами. В процедурах определены отношение вложенности и пара несимметричных операций ВЫЗОВ и ВОЗВРАТ. Сопрограммы, так же как и процедуры могут вызывать друг друга, но между ними нет отношения вложенности, а вместо несимметричной пары операций ВЫЗОВА и ВОЗВРАТА существует одна операция, которую чаще всего называют ПЕРЕДАТЬ УПРАВЛЕНИЕ. Т. е., если определены сопрограммы р1 и р2, то определена операция ПЕРЕДАТЬ УПРАВЛЕНИЕ (от кого, кому). При передаче управления от одной сопрограммы к другой, выполнение первой сопрограммы приостанавливается, а ее состояние запоминается, таким образом, что когда приостановленной сопрограмме снова передается управление, она продолжает свое выполнение именно с той точки, на которой была приостановлена.

В различной литературе существуют разные нотации для описания сопрограмм. Существует термин "restart p" (Краковяк), существует термин "resume p" (Шоу). Мы в дальнейшем будем пользоваться обозначением Transfer (от кого, кому), которое используется при реализации сопрограмм в языке Модула-2.

Внешне взаимодействие двух сопрограмм может быть описано следующей схемой:

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

Получаем моделирование параллельного выполнения двух программ.

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

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

Существует текущий стек, т. е. стек, на который указывают регистры ss:sp. Это стек той сопрограммы, которая выполняется в данный момент. Передача управления с помощью операции transfer(p1,p2) - это, по сути, замена стека.

Свяжем с каждой из сопрограмм собственный стек.

Операция transfer - это вызов процедуры, который происходит на текущем стеке. Вызов осуществляется инструкцией call. При вызове, в стек записываются cs и ip. Это точка в сопрограмме, находящаяся сразу же за вызовом transfer. Теперь внутри процедуры transfer переключим стек на другую область памяти - на стек другой сопрограммы. Будем считать, что он находится в состоянии, похожем на стек первой сопрограммы. Т. е. в нем находится адрес той точки сопрограммы, которая находится за вызовом transfer, приостановившим выполнение сопрограммы когда-то раньше. Возврат из процедуры transfer осуществляется инструкцией ret, но выполняется он уже на стеке новой сопрограммы. Инструкция ret выталкивает из этого нового стека в регистры cs и ip адрес той точки сопрограммы, с которой и надо продолжить выполнение.

Т.к. внутри процедуры transfer мы устанавливаем новые значения регистров ss:sp, указывающие на область памяти – вершину стека возобновляющей выполнение сопрограммы, то, во-первых, необходимо откуда-то брать эти новые значения, а, во-вторых, нам необходимо где-то запоминать состояние области памяти – вершины стека приостанавливаемой сопрограммы. Отсюда появляется структура данных, которую назовем ДЕСКРИПТОР сопрограммы, и которая должна хранить адрес вершины стека сопрограммы, когда она приостанавливается. Термин ДЕСКРИПТОР очень распространен в науках об операционных системах. Таким термином описывают структуры данных, хранящие информацию об объектах среды. Как правило, через дескрипторы осуществляется доступ к объектам.

В нашем минимальном варианте дескриптор хранит адрес ячейки памяти, являющейся вершиной стека соответствующей сопрограммы. Тогда ясным становится следующее описание дескриптора:

typedef struct {

int ssreg;

int spreg;

} tdescriptor;

В дальнейшем мы будем усложнять описание дескриптора, дополняя его данными при усложнении понятия сопрограммы. Таким образом, процедура transfer должна писать состояние регистров ss:sp в дескриптор приостанавливаемой сопрограммы, а устанавливать новые значения регистров ss:sp из дескриптора возобновляемой сопрограммы. Т. е. процедуре transfer должны быть переданы адреса двух дескрипторов - дескриптора приостанавливаемой сопрограммы и дескриптора возобновляемой сопрограммы.

С учетом механизма передачи параметров в процедуру через стек, картинка со стеками сопрограмм немного усложнится:

Здесь через D1 и D2 обозначены дескрипторы сопрограмм р1 и р2. Таким образом сопрограмма помимо собственного стека характеризуется еще и наличием дескриптора, хранящего состояние этого стека.

Начальная инициализация сопрограмм

Мы рассмотрели установившийся режим работы сопрограмм, когда они возобновляют свое выполнение после приостановки с помощью вызова transfer. «Возобновление» в первый раз, т. е. передача управления с помощью функции transfer сопрограмме, которая до этого не приостанавливалась функцией transfer, требует специальной инициализации.

Эта инициализация включает в себя:

  1. Выделение памяти под дескриптор;

  1. Выделение памяти под стек;

  1. Занесение в стек точки входа в сопрограмму;

  1. Занесение в дескриптор адреса вершины стека.

Поскольку первое «возобновление» все равно происходит под действием функции transfer, необходимо в инициализируемом стеке предусмотреть операции, выполняемые этой функцией. Эти операции следующие:

  1. Выталкивание из вершины стека слова в регистр bp;

  1. Выполнение инструкции ret, выталкивающей следующие два слова (точку входа в сопрограмму) в ip и cs;

  1. Сдвиг указателя стека вниз (в сторону старших адресов) на 4 слова (8 байтов) - освобождение области стека, через которую в установившемся режиме передаются адреса дескрипторов.

С учетом эти операций инициализированный стек должен выглядеть следующим образом:

Стек

под pop bp

14

ofs т. входа

12

seg т. входа

10

под ofs D2

8

под seg D2

6

под ofs D1

4

под seg D1

2

0

Этот адрес

возвращает функция new

Этот адрес надо записать в дескриптор

Это адрес дна стека

Чтобы получить адрес дна стека, необходимо к адресу, возвращенному функцией new, прибавить размер стека. От адреса дна стека надо отнять 14, чтобы получить адрес вершины стека при инициализации. К этому адресу надо прибавить 2, чтобы записать туда смещение точки входа в сопрограмму, и прибавить еще 2, чтобы записать туда сегмент точки входа в сопрограмму.

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

transfer

Среда выполнения сопрограмм

Не всегда, когда по существу речь идет о сопрограммах, используется термин «сопрограмма». Далее мы рассмотрим два примера такой ситуации.

Соседние файлы в предмете Операционные системы