АкушерствоАнатомияАнестезиологияВакцинопрофилактикаВалеологияВетеринарияГигиенаЗаболеванияИммунологияКардиологияНеврологияНефрологияОнкологияОториноларингологияОфтальмологияПаразитологияПедиатрияПервая помощьПсихиатрияПульмонологияРеанимацияРевматологияСтоматологияТерапияТоксикологияТравматологияУрологияФармакологияФармацевтикаФизиотерапияФтизиатрияХирургияЭндокринологияЭпидемиология

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

Прочитайте:
  1. HLA- DR, DQ, DP. В этой же зоне находятся и другие гены: например, DN, DO, продукты которых пока не известны.
  2. III. После этого раненую конечность лучше всего зафиксировать, например, подвесив на косынке или при помощи шин, что является третьим принципом оказания помощи при ранениях.
  3. IV. Опухоли мягких тканей и опухолевидные процессы
  4. IV. Порядок проведения и примерное распределение времени
  5. V. Опухолевидные процессы
  6. А. Острое действие комплекса.
  7. Адгезивные молекулы (молекулы суперсемейства иммуноглобулинов, интегрины, селектины, муцины, кадхерины): строение, функции, примеры. CD-номенклатура мембранных молекул клеток.
  8. Адсорбционные равновесия и процессы на подвижной и неподвижной границах раздела фаз. Влияние различных факторов на величину адсорбции.
  9. Актуальный пример разработки программы в случае моббинга
  10. Алоэ Вера питьевой гель LR - Примеры выздоровлений.

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

На этом рисунке программа с именем А в точке 1 порождает сразу четыре парал­лельно выполняющихся задачи (вычислительных процесса): В, С, I и J. Процес­сы В и С завершаются и должны запустить, в свою очередь, два параллельных процесса D и Е. В точке 2, в которой происходит синхронизация задач В и С, процессы D и Е должны быть запущены той из задач В или С, которая закончит


свое выполнение раньше, но только после момента окончания второй. Далее, в точке 3 необходимо запустить программы G и Н. Запускает их первая завершив­шая свою работу программа (D, Е или I), но дождавшись завершения остальных программ. Точка 4 синхронизирует выполнение процессов F, G, H и J, при этом программу К запускает последний из завершившихся процессов.

Для решения поставленной задачи будем использовать соответствующие меха­низмы, описанные нами выше (применительно к OS/2), а именно конвейер (pipe) и семафоры. В нашей задаче через конвейер передается переменная типа Parent-Info:

struct Parentlnfo { char ParentName [15]: char LaunchTime [12]: int Number: }

Parentlnfo — хранит имя программы-предка; LaunchTime — содержит время запус­ка текущей программы программой-предком (время, когда программа-предок выполнила функцию DosExecPgn); переменная Number указывает, для какого числа программ предназначена переменная Parentlnfo.

Читать из конвейера мы можем при помощи функции DorRead, но при этом унич­тожается запись в конвейере, и мы обязаны перезаписывать данные в конвейер для других программ. Каждая программа читает данные из конвейера и затем уменьшает значение Number. Программа, установившая значение 1, является по­следней программой, прочитавшей данные из конвейера; она посылает сигнал предку о завершении инициализации необходимых ресурсов. Программа пишет в конвейер данные только в том случае, если именно она будет запускать сле­дующие программы.

Для чтения и записи в конвейер необходимы переменные WriteHandle и ReadHandle, указывающие на описатели записи и чтения в конвейер. Необходимо, чтобы зна­чения этих переменных, полученных в процессе А, были известны остальным процессам для совместного использования. Для этого значения этих переменных мы можем передать процессам-потомкам в качестве строк аргументов.

При попытке считывания информации из пустого конвейера процесс переводит­ся в состояние ожидания. После записи информации в конвейер другим процес­сом ожидающий процесс считывает поступившую информацию и продолжает свою работу.

Поскольку программы, которые мы сейчас рассматриваем, созданы для операци­онной системы OS/2, приведем краткое описание использованных механизмов, которые имеют отличия от вышеописанных общих принципов и схем.

Q Функция создания семафора:

DosCreateEventSem ("\\SEM\\PIPESEM". UPipeSem. 1. 0):

где "\\SEM\\PIPESEM" — имя семафора, PipeSem — идентификатор семафора, 1 — параметр совместного использования семафора (DC_SEM_SHARED), 0 — зарезер­вированный системный параметр.


D Функция открытия семафора:

DosOpenEventSem ("\\SEM\\PIPESEM". SPipeSem):

где "\\SEM\\PIPESEM" — имя семафора, PipeSem — идентификатор семафора.

О Функция установки семафора: DosPostEventSem (PipeSem): где PipeSem — идентификатор семафора.

Q Функция сброса семафора:

DosResetEventSem (PipeSem. &NPost):

где PipeSem — идентификатор семафора, NPost — количество обращений к ус­тановке семафора с момента последнего сброса.

Q Функция ожидания установки семафора:

DosPostEventSem (PipeSem. -1):

где PipeSem — идентификатор семафора, -1 — ожидание семафора до его уста­новки (положительное значение — это задержка в миллисекундах).

Для синхронизации процессов и обработки критических участков программ не­обходимы семафоры, к которым имеют доступ все работающие программы. Про­грамма-потомок может унаследовать семафор от программы-предка, которая создала или открыла необходимый семафор. Но это произойдет только тогда, когда программа-предок дождется момента открытия семафора в программе-по­томке. Это обеспечивается за счет дополнительных семафоров ExitSeml, ExitSem2, ExitSemS. Когда последняя программа-потомок прочитывает данные из конвейера (работа с конвейером) и обнаруживает, что она последней прошла участок от­крытия уже созданных семафоров, она устанавливает необходимый семафор, принадлежащий программе-предку: Программа-предок, ожидающая установки семафора, завершает свою работу.

Для управления запуском и завершением программ также используются соот­ветствующие функции.

DosExecPgm (FailFile, sizeof(FailFile), 1, Argument, 0, ResCode, "progr_b.exe") — функция запуска программы-потомка, где

Q Fail File — буфер для'помещения имени объекта, из-за которого возникла ошиб­ка запуска программы, sizeof(FailFile) — размер буфера;

Q 1 означает, что процесс-потомок следует выполнять асинхронно с процессом-предком, Argument — строки аргументов программы, 0 — строки среды, ResCode — результирующие коды запуска программы, "progr_b.exe" — имя запускаемой (планируемой на выполнение) программы;

D DosExit — функция завершения процесса (и всех его подпроцессов);

Q DosSetPriority — установка приоритета программы (и всех его подпроцессов).

Каждую программу в соответствии с заданием создаем как независимую, то есть имеющую свое локальное адресное пространство. Благодаря этому переменные в текстах программ, имеющие одинаковые имена (см. листинги в приложении Б), фактически являются разными переменными.


Программа с именем А является начальной, стартовой. Именно она создает те системные объекты, которыми потом пользуются ее потомки для своей синхро­низации. Имена системных объектов они получают в наследство при своем по­рождении.

Для совместного использования вычислительными процессами одного файла необходимо правильно его открыть в программе А. После корректного открытия или создания файла к нему могут обращаться все программы, имеющие иден­тификатор открытого файла. Значение этого идентификатора передается запус­кающимся процессам в строке аргументов, сопровождающих вызов.

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

Опишем теперь алгоритм обработки критических участков программ — записи в файл и работы с конвейером.

Q Критический участок — работа с конвейером.

Приведем фрагмент программы, обеспечивающий чтение из конвейера.

1: do { DosWaitEventSem (PipeSem. -1):

2: rc=DosResetEventSem (PipeSem. &NPost):

3: } while (rc!-0);

4: DosRead (ReadHandle. (PVOIDJ&Oldlnform. sizeof(Oldlnform). BytesReaden):

5: DosPostEventSem(PipeSem):

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

В строке 1 программа ожидает установки семафора PipeSem; после того как этот семафор будет установлен, программа переходит к строке 2. Переменная гс возвращает код ошибки при попытке сбросить семафор в строке 2. Это сде­лано со следующей целью: если после завершения строки 1 будет выполнять­ся другая программа и она успеет сбросить семафор, то когда программа вновь продолжит свое выполнение, она обнаружит в строке 2, что семафор уже сброшен и гс не будет равно нулю; затем цикл повторится. Так будет про­должаться до тех пор, пока гс не станет равно нулю, то есть текущая програм­ма первой сбросила семафор. Тогда в строке 4 программа считывает из кон­вейера данные и сигнализирует об освобождении ресурса в строке 5.

Для записи в конвейер используется аналогичный алгоритм. Q Критический участок — запись в файл.

Здесь использован такой же алгоритм, как и при работе с конвейером, но за­действован специально созданный для этого семафор FileSem.


Теперь рассмотрим алгоритмы, решающие задачи синхронизации в каждой из точек нашей схемы (см. рис. 6.7). Начнем с прохождения точки 2. Приведем фрагмент исходного текста программы (см. приложение Б).

1: rc-DosPostEventSem(Pol ntlSem); 2: if (re—0)

3: { DosWrite(WriteHandle.(PVOID)&NewInform. sizeof(NewInform).&BytesWritten): 4: DosCreateEventSem("\\SEM32\\EXITSEM2", &ExitSem2. DC_SEM_SHARED. 0): 5: DosExecPgm(FailFileb.sizeof(FailFileb).l. Argument.0. SResCodeb."progr_d.exe"): 6: DosExecPgm(FailFileb.sizeof(FailFileb).l. Argument.0. &ResCodeb."progr_e.exe"): 7: DosExecPgm(FailFileb.sizeof(FailFileb).l.Argument.0. &ResCodeb."progr_f.exe"); 8: DosWaitEventSem(ExitSem2.-l): 9: DosCloseEventSem(Ex1tSem2): }

В точке 2 программы D, E, и F должны быть запущены процессом, который пер­вым завершит свою работу. Для определения последовательности завершения работы программ (В или С) нами используется семафор PointlSem. В строке 1 производится установка данного семафора. Если значение гс не равно нулю, зна­чит, семафор уже установлен, то есть текущая программа не первой завершила свою работу. Если гс равно нулю, то текущая программа закончила работу пер­вой и осуществляется переход к строке 3. В строке 3 осуществляется запись в конвейер. Строка 4 — создание семафора ожидания. Этот семафор используется для ожидания открытия семафоров в программах-потомках. Ожидание откры­тия семафоров происходит в строке 8, затем семафор закрывается. В строках 5—7 осуществляется запуск программ D, E, F.

Теперь приведем алгоритм прохождения точки 3. Фрагмент исходного текста программы изображен ниже.

1: rc-DosPostEventSem(Point2Sem):

2: if (гс- =0)

3: { do{ DosQueryEventSem(Point2Sem.&BytesWritten):

4: jwhile (BytesWritten<=2);

5: DosWrite(WriteHandle.(PVOID)&NewInform. sizeof(NewInform), &BytesWritten):

6: DosCreateEventSemt"\\SEM32\\EXITSEM3", &ExitSem3. DC_SEM_SHARED. 0);

7: DosExecPgm(FailFileb.sizeof(FailFileb),l.Argument.0. SResCodeb."progr_g.exe");

8: DosExecPgm(FailFileb,sizeof(FailFileb).l.Argument.0. &ResCodeb."progr_h.exe");

9: DosWaitEventSem(ExitSem3.-l);

В точке 3 программы G и Н запускаются той программой, которая первой завер­шает свою работу, но только после того, как работу завершат остальные програм­мы. Для определения последовательности завершения работы программ (I, D или Е) используется семафор Point2Sem. В строке 1 производится установка дан­ного семафора. Если значение гс не равно нулю, значит, семафор уже установ­лен, то есть текущая программа не первой завершила свою работу. Если гс равно нулю, то текущая программа закончила работу первой и осуществляется переход к строке 3. В этой строке подсчитывается количество обращений к данному семафору. Цикл повторяется до тех пор, пока количество обращений не станет равно 3, то есть когда все остальные программы завершили свою работу. После этого в строке 5 осуществляется запись в конвейер. Строка 6 — создание семафо­ра ожидания. Этот семафор используется для ожидания открытия семафоров


в программах-потомках. Ожидание открытия семафоров происходит в строке 9. В строках 7 и 8 осуществляется запуск программ G и Н соответственно.

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

1: do { DosWaitEventSem(PointlSem.-l):

2: rc=DosResetEventSem(PointlSem.&BytesReaden):

3: } while (rc!-0):

4: DosPostEventSem(Point3Sem):

5: DosQueryEventSem(Point3Sem,&BytesWhtten):

6: DosPostEventSem(PointlSem):

7: if (BytesWritten==4)

8: { DosWr1te(Wr1teHandle,(PVOlD)&NewInform, sizeof(NewInform).&BytesWritten):

9: DosCreateEventSemt"\\SEM32\\EXITSEM4". &ExitSem4. DC_SEM_SHARED. 0):

10: DosExecPgmtFailFileb.sizeof(FailFileb),!.Argument.0. &ResCodeb."progr_k.exe"):

11: DosWaitEventSem(ExitSem4.-l):

Итак, в точке 4 программа К запускается задачей, которая последней завершила свою работу. Для определения последовательности завершения работы программ (J, G, Н или F) используется семафор Point3Sem. Каждая программа должна обра­титься к данному семафору, установить его и проверить количество обращений к нему. Но при выполнении этих двух операций другие программы могут также установить семафор, и значение обращений к семафору в текущей программе окажется неверным. Для доступа к семафору PointSSem используется семафор PointlSem. В строке 1 программа ожидает установки семафора PointlSem, который сигнализирует о доступности неразделяемого ресурса Point3Sem. В строке 2 сема­фор сбрасывается, но если другие программы успели сбросить семафор, то об этом сообщит значение гс. Если текущей программе удалось завладеть ресурсом, то есть значение гс равно нулю, то дальше в строках 4, 5 производится установка семафора Poi nt3Sem и подсчет количества обращений. Строка 6 сигнализирует о завершении работы критической части программы установкой семафора PointlSem. Затем, как и в предыдущих алгоритмах, программа записывает информацию в транспортер (строка 8), создает семафор ожидания открытия семафоров в про­граммах-потомках (строка 9), запускает программу К (строка 10) и ожидает от­крытия семафоров в программе К (строка 11).

Тексты четырех программ (А, В, D и G), действующих по рассмотренным алго­ритмам, приведены в приложении Б. Остальные программы аналогичны им и от­личаются только использованием других имен.

Контрольные вопросы и задачи

Вопросы для проверки

1. Какие последовательные вычислительные процессы мы называем параллель­ными и почему? Какие параллельные процессы называются независимыми, а какие — взаимодействующими?


2. Изложите алгоритм Деккера, позволяющий разрешить проблему взаимного
исключения путем использования одной только блокировки памяти.

3. Объясните команду «проверка и установка».

4. Расскажите о семафорах Дейкстры. Чем обеспечивается взаимное исключе­
ние при выполнении Р- и V-примитивов?

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

6. Что такое мьютекс (mutex)?

7. Изложите алгоритм решения задачи «поставщик — потребитель» при исполь­
зовании семафоров Дейкстры.

8. Изложите алгоритм решения задачи «читатели — писатели» при использова­
нии семафоров Дейкстры.

9. Что такое «монитор Хоара»? Приведите пример такого монитора.

 

10. Что представляют собой «почтовые ящики»?

11. Что представляют собой «конвейеры» (программные каналы)?

12. Что представляют собой «очереди сообщений»? Чем отличаются очереди со­
общений от почтовых ящиков?


Дата добавления: 2015-01-18 | Просмотры: 768 | Нарушение авторских прав



1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |



При использовании материала ссылка на сайт medlec.org обязательна! (0.009 сек.)