Файл: Учебнометодическое пособие Томск 2016 2 удк 004. 451(075. 8) Ббк 32. 973. 2018. 2я73 к 754 Рецензенты.pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 25.10.2023
Просмотров: 290
Скачиваний: 2
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
102 выполнения общесистемных функций, поддерживающих работоспособность системы. Например, демоном является процесс init.
Пользователь системы является первичным источником сигналов не только при нажатии им одной из специальных комбинаций клавиш, которые были рассмотрены нами выше. Он может выдать требуемый сигнал нужному процессу, используя команду shell– kill:
$ kill – сигнал процесс, где сигнал– имя сигнала (номер или символьное имя), предваряемое симво- лом «–». Этот параметр необязателен. Если он опущен, то по умолчанию посы- лается сигналSIGTERM (просьба о добровольном завершении процесса); про- цесс – номер того процесса, которому направляется сигнал.
Администратор системы может послать сигнал любому процессу, а обычный пользователь – только своему. Для определения номера требуемого процесса используется команда ps (рассматривается в п. 3.2). Кроме того, для задания номера процесса иногда оказывается полезной внутренняя пере- менная shell с именем «!». Эта переменная содержит номер того процесса, который был запущен последним в фоновом режиме. Как и другие внутренние переменные shell, значение переменной «!» задается самимshell, и поэто- му ни в командных строках, ни в скриптах имя данной переменной никогда не встречается без предварительной записи символа «$», наличие которого озна- чает «значение переменной».
· · · · · · · · · · · · · · · · · · · · · · · · · ·
Пример
· · · · · · · · · · · · · · · · · · · · · · · ·
Следующая команда посылает в процесс, запущенный последним в фоно- вом режиме, сигнал SIGKILL, выдача которого приводит к жесткому прекра- щению процесса без сохранения какой-либо информации о его завершении:
$ kill –SIGKILL $!
Для выполнения команды killshell использует свою внутреннюю подпрограмму. Применение данной команды не ограничивается управлением готовыми процессами, что позволяет, например, уничтожать процессы, нахо- дящиеся в тупике. Ее применение позволяет также имитировать выдачу любого сигнала с целью проверки правильности его обработки программой процесса, что весьма полезно при разработке этой программы.
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
103
3.4.3 Синхронизация конкурирующих процессов
В однопрограммной ВС единственным способом реализации информаци- онного обмена между программными модулями (программами и подпрограм- мами) является использование общей памяти, доступной для взаимодействую- щих модулей. В качестве такой памяти могут использоваться рабочие регистры
ЦП, стек, другие области ОП. В мультипрограммной системе для информаци- онного взаимодействия между процессами не могут использоваться ни реги- стры ЦП, ни программный стек, так как каждый из процессов пользуется своим набором этих модулей (регистры ЦП разделяются процессами виртуально, а стеки изолированы между собой физически).
Единственный тип области ОП, пригодный для непосредственного ин- формационного взаимодействия между процессами – разделяемый сегмент данных. Принципиальное отличие такого сегмента от разделяемого сегмента кода, содержащего реентерабельную программу или DLL, состоит в том, что программы процессов могут не только читать из этого сегмента, но и вы- полнять в него запись. Назначение процессам разделяемого сегмента данных выполняется ОС и будет рассмотрено нами позднее (в п. 6.2). Сейчас нам важно уяснить, что без дополнительной синхронизации процессов наличия разделяе- мого сегмента явно недостаточно для их информационного взаимодействия.
Для того чтобы показать это, рассмотрим следующую задачу.
Допустим, что процесс-сервер выполняет запросы процессов-клиентов по распечатке текстовых файлов на принтере. При этом информационное взаимо- действие клиентов и сервера осуществляется через разделяемый сегмент памя- ти (рис. 3.3). В этом сегменте расположена структура данных – связанная оче- редь, в которую процессы-клиенты помещают свои запросы на обслуживание
(имена текстовых файлов), а процесс-сервер извлекает эти запросы из очереди по одному и выполняет.
Обычно в разделяемой области памяти находится не одна, а несколько переменных. Если два процесса могут работать с одной и той же переменной x, причем по крайней мере один из них может выполнять запись в x, то говорят, что эти два процесса являются конкурирующими из-за x.
Например, в рассматриваемом примере разделяемый сегмент содержит три переменные: очередь (массив), а также указатели S и F, являющиеся указа- телями на начало и конец очереди. Процессы-клиенты конкурируют из-за оче- реди, а также из-за F. Любой клиент конкурирует с сервером из-за очереди. По-
104 кажем, что конкурирующие процессы обязательно должны быть синхронизиро- ваны.
Рис. 3.3 Три процесса разделяют сегмент памяти
Допустим, что в какой-то момент времени очередь имеет состояние, при- веденное на рисунке 3.4, а. Пусть клиент 1 хочет поместить в очередь эле- мент y, а клиент 2 – элемент z. Очередь, измененная в результате правильного включения, приведена на рисунке 3.4, б.
Рис. 3.4 Состояния очереди:
а – исходное; б – правильное включение элементов y и z
Но возможен другой исход, если учесть, что операция включения элемен- та в очередь состоит из трех более мелких операций:
1) чтение переменной F, указывающей на последний элемент в списке;
2) корректировка указателя в элементе n на новый элемент;
3) запись в F указателя на новый элемент.
Допустим, что клиент 1 успел выполнить операции 1 и 2. Потом он был прерван на некоторое время, в течение которого клиент 2 выполнил все три операции. Потом клиент 1 смог выполнить операцию 3. Соответствующие из- менения очереди приведены на рисунке 3.5. В результате единая очередь оказа-
105 лась разорванной на две несвязанные части, что недопустимо. Рассмотрим, как этого можно избежать.
Рис. 3.5 Возможное преобразование очереди при отсутствии синхронизации
Пусть два процесса p1 и p2 конкурируют из-за переменной x. При выпол- нении действия конкурирующего процесса с переменной, как правило, выпол- няется не один, а целая группа операторов соответствующей программы. Каж- дая такая группа называется критической секцией. В принципе никаких ошибочных взаимодействий между процессами не будет, если им запретить од- новременно выполнять свои критические секции. Рассмотрим подходы для обеспечения этого.
106
Первый, наиболее очевидный подход заключается в том, чтобы на время выполнения процессом своей критической секции вообще запретить выполне- ние других процессов на ЦП. Такой подход используется довольно широко в обработчиках аппаратных прерываний, которые на время выполнения своих критических секций производят запрет внешних (маскируемых) аппаратных прерываний. Недостаток такого подхода: допускается делать запрет внешних прерываний лишь на очень короткое время. (Обработчики внешних аппаратных прерываний могут рассматриваться как процессы реального времени, для каж- дого из которых есть предельное время реакции.) Другой недостаток: данный метод применим лишь в однопроцессорных ВС. В системе с несколькими ЦП запрет прерываний в одном ЦП не влияет на выполнение программ на других
ЦП.
Другое применение этого же подхода: в системе UNIXвыполнение про- цесса не может быть прервано в состоянии «Ядро» другими процессами.
Это обеспечивает целостность системных данных, так как работа с этими дан- ными производится процессом только в состоянии «Ядро».
Второй подход предполагает запрещение выполнения, на время выполне- ния процессом своей критической секции, не всех процессов, а лишь тех, кото- рые конкурируют с ним из-за этой же переменной. Для этого перед входом в свою критическую секцию процесс посылает сигнал запрета своим конкурен- там. После выхода процесса из критической секции он посылает процессам- конкурентам сигнал разрешения. С другой стороны, каждый процесс перед входом в свою критическую секцию проверяет, какой из двух сигналов он по- лучил последним. Если это сигнал разрешения, то процесс сам посылает сигнал запрета. Недостатком метода является то, что процессы должны находиться не просто в дружеских отношениях, при отсутствии которых сигналы могут во- обще игнорироваться процессом, а в родственных отношениях, требуемых для определения номера процесса. Другой недостаток: лишние затраты времени ЦП при ожидании процессом доступа в свою критическую секцию.
Третий подход заключается в использовании для управления доступом к разделяемым переменным двоичных переменных (флагов). Эти флаги нахо- дятся в разделяемой области, и каждый из них управляет доступом к одной пе- ременной: если флаг установлен, то работать с переменной можно, а если сброшен, то нельзя. Перед входом в критическую секцию процесс проверяет значение флага. Если он сброшен, то процесс в цикле ожидает его установки.
Очевидно, что в течение текущего кванта времени ЦП процесс этого не до-
107 ждется, и время ЦП будет истрачено зря. Другой недостаток: проверку уста- новки флага и переход в случае успеха должна выполнять одна неделимая ма- шинная команда. Если это не так, то возможна ситуация, когда после выполне- ния команды проверки флага процесс будет прерван своим конкурентом, что может привести к непредсказуемому результату.
Четвертый подход является развитием предыдущего, позволяя избавиться от бесполезных затрат времени ЦП на ожидание освобождения разделяемой переменной. Это использование семафоров Дейкстры.
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
1 ... 6 7 8 9 10 11 12 13 ... 23
Семафором Дейкстры S называется целая неотрицательная
переменная S = 0; 1; 2; 3; 4..., над которой допустимы две опера-
ции:
1) v (S) – переменная S увеличивается на 1;
2) p (S) – переменная S уменьшается на 1, если это воз-
можно. Если S = 0, то ее уменьшить нельзя и процесс,
содержащий p(S), будет ждать (в состоянии «Сон») до
тех пор, пока S не станет > 0 и операция p(S) не ста-
нет возможной.
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
Операции v(S) и p(S) реализуются или аппаратно (в виде одной ма- шинной команды), или программно. Алгоритмы этих операций: p(S):
ЕСЛИ
S > 0
ТО
S
S – 1; продолжение выполнения процесса
ИНАЧЕ блокирование процесса по S вызов диспетчера ЦП v(S):
ЕСЛИ (очередь процессов, ожидающих S, непу- стая)
ТОдеблокирование процесса, блокированного по S
ИНАЧЕ
S
S + 1; продолжение выполнения процесса
Здесь действие «блокирование процесса по S» означает, что, во-первых, процесс переводится в состояние «Сон», а во-вторых, процесс (а точнее его но- мер) помещается в очередь процессов, каждый из которых ожидает завершения
108 своей операции p(S). Очередь процессов – структура данных, обязательно присущая любому семафору. В ней находятся процессы, ожидающие получения того ресурса, который контролируется данным семафором S. (В нашем случае таким ресурсом является разделяемая переменная.) В случае блокирования процесса вызывается диспетчер ЦП с целью установки на ЦП какого-то про- цесса, ожидающего доступа к ЦП.
Если семафор S может принимать только два значения (0 и 1), то он называется двоичным семафором. Для синхронизации любого числа процессов, конкурирующих между собой из-за некоторой переменной x, достаточно:
1) выделить в программе каждого процесса критические секции, каждая из которых выполняет некоторое действие над x;
2) задать начальное значение двоичного семафора S, равное 1;
3) записать перед каждой критической секцией оператор p(S), а после нее – v(S).
3.4.4 Синхронизация кооперирующихся процессов
Два процесса, совместно использующие общую переменную, могут не только конкурировать из-за нее, но и кооперироваться. Кооперирующиеся
процессы – процессы, выполняющие общую работу, которая заключается в том, что один процесс («писатель») выполняет запись в общую структуру данных
(буфер), а другой процесс («читатель») выполняет считывание данных оттуда.
Например, в приведенном ранее примере со связанной очередью каждый про- цесс-клиент является «писателем», а процесс-сервер – «читателем». Поэтому процесс-сервер образует с каждым процессом-клиентом пару кооперирующих- ся процессов.
Кооперирующиеся процессы нуждаются в синхронизации, во-первых, для того, чтобы процесс-писатель не записывал в буфер тогда, когда он уже по- лон. Во-вторых, процесс-читатель не должен читать из буфера тогда, когда он пуст. Для подобной синхронизации могут быть использованы сигналы, но го- раздо удобнее использовать для этого семафоры Дейкстры.
Допустим, что несколько процессов-«писателей» выполняют запись эле- ментов данных в буфер, а несколько других процессов-«читателей» выполняют чтение элементов данных из этого же буфера. Пусть емкость буфера составляет n элементов. Тогда для синхронизации их деятельности достаточно ввести два семафора – S1 и S2. Семафор S1 управляет работой «писателей». Его значение
109 есть число пустых позиций в буфере. Семафор S2 управляет работой «читате- лей». Его значение есть число занятых позиций в буфере. Первоначальные зна- чения: S1 = n, S2 = 0. Так как при работе с буфером кооперирующиеся про- цессы одновременно являются и конкурирующими, то для исключения одновременной работы с буфером введем двоичный семафор S3. Возможные программы процессов:
ПРОЦЕСС-ПИСАТЕЛЬ:
M1: подготовка элемента данных p(S1) p(S3) запись элемента данных в буфер v(S3) v(S2) переход M1
ПРОЦЕСС-ЧИТАТЕЛЬ:
M2: p(S2) p(S3) чтение элемента данных из буфера v(S3) v(S1) обработка элемента данных переход на M2
3.5 Информационные взаимодействия между процессами
Разделяемая память является наиболее быстрым средством межпроцесс- ного информационного взаимодействия, так как при ее применении, во-первых, не требуется применение ВП, а во-вторых, не требуются какие-либо переносы данных внутри ОП. Но возникающие при ее использовании проблемы синхро- низации делают необходимым применение семафоров Дейкстры, что суще- ственно ограничивает возможности применения данного средства информаци- онного взаимодействия по следующим причинам.
110
Во-первых, программы всех процессов, разделяющих какие-то области
ОП, должны содержать правильно записанные системные вызовы p(S) и v(S)
. При этом пропуск хотя бы одного такого вызова или нарушение порядка их записи приведет к ошибкам синхронизации. Во-вторых, каждый взаимодей- ствующий процесс должен сам знать, где находится разделяемая переменная, так как используемый метод синхронизации об этом ничего не говорит. Подоб- ным требованиям могут отвечать только процессы, находящиеся в «друже- ственных отношениях». Такие отношения обычно имеются у процессов, сов- местно выполняющих единую параллельную программу. Другие параллельные процессы не находятся в таких отношениях ни между собой, ни по отношению к разделяемой переменной. В этом случае все операции по синхронизации до- ступа к разделяемой переменной должны быть выведены из прикладной части процесса.
Другие средства информационного обмена, предоставляемые процессам со стороны ОС, не требуют от этих процессов какой-либо синхронизации. В от- личие от разделяемой памяти эти методы предполагают перенос данных из об- ласти памяти, доступной процессу-источнику в область памяти, доступную процессу-потребителю. Такой перенос выполняется всегда через области памя- ти (ОП и ВП), находящиеся в ведении ОС и недоступные непосредственно про- цессам. Иными словами, ОС предоставляет в распоряжение процессов инфор-
мационные каналы (рис. 3.6).
Рис. 3.6 Взаимодействие процессов через информационный канал