Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Страничной виртуальной памяти.




 

Лекция 4.Операционная система. Общие характеристики и свойства.

Операционная система – это комплекс программ, обеспечивающий контроль за существованием, распределением и использованием ресурсов ВС.

Расшифруем:

существование – логические и виртуальные ресурсы существуют за счет распределения и использования ресурсов ОС;

 

распределение – современные ОС всегда многопроцессовые;

 

использование – проблема организации контроля за использованием, например, учет времени ЦП.

 

Процесс – это одно из базовых понятий. Синонимами процесса являются управление задачами, заданиями. Каждая ОС рассматривает некоторую сущность, которую мы называем процессом. Это элементарная единица, которая осуществляет управление ОС. Это совокупность машинных команд и данных, исполняющаяся в рамках ВС и обладающая правами на владение некоторым набором ресурсов.

 

Важнейшее св-во процесса – набор ресурсов:

монопольно принадлежащих данному процессу;

разделяемых (принадлежащих 2м или более процессам).

 

В настоящее время проблема организации разделяемых ресурсов довольно существенна.

Существуют 2 модели:

1) предварительная декларация необходимых ресурсов (объем памяти, номера виртуальных страниц => запуск процесса);

2) модель динамического дополнения списка ресурсов (запуск процессов, в которых нужен только стартовый объем пакета, а остальное выделяется по необходимости.

Достоинства: Первая модель более строгая, а вторая более гибкая.

 

В независимости от того, какие функции способна выполнять ОС, она должна удовлетворять пяти основным свойствам:

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

2. Защита. Имеется в виду защита и персонификация данных пользователей. Этой темы мы коснемся позже.

3. Эффективность. Обычно ОС представляет собой сложную программу, которая использует значительную часть аппаратных ресурсов для своих собственных надобностей. Ресурсы, которые потребляет ОС, не поступают в распоряжение пользователей. Следовательно, сама система должна быть как можно более экономной. Кроме того, система должна управлять ресурсами пользователей так, чтобы добиться максимальной загруженности ресурса в те доли времени, когда ресурс не простаивает (В большей степени это касается загруженности процессора (процессоров)).

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

5. Удобства. ОС должна быть гибкой и удобной для пользования. Очевидно, что это свойство сугубо субъективно.

 

Структура ОС.

Ядро (kernel) – резидентная часть ОС, работающая в режиме супервизора. («обычно» работает в режиме физической адресации).

 

Интерфейсы системных вызовов

(API – Application Program Interface)

||

Динамически подгружаемые драйверы физических и

виртуальных устройств – обращение

к ним не требует сверх аппарата.

||

Ядро ОС – программы обработки прерываний

и драйверы наиболее быстрых устройств.

 

Автоматически включается режим супервизоров.

 

«Системный вызов» - обращение к ОС за предоставление той или

иной функции (возможности, услуги, сервиса).

 

Описание ó стандартная библиотека

программ.

 

Существует 2 уровня организации ОС:

1) пользовательский, на котором программист пользуется библиотекой через системные вызовы. Реализуется т.н. монолитное ядро – достаточно большой компоновщик, включающий взаимодействие процессоров, драйверы и т.п.

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

 

       
   
 

 

       
 
   
аппаратура
 

 

 


Логические ф-ции ОС

 

•управление процессами

суть в функциях ОС, которые обеспечивают образование процесса и его выполнение в рамках ОС.

управление ОП

ОС может реализовывать разные стратегии распределения ОП и степени защиты

 

•планирование

выбор очередности программ для начала обработки, распределение энергии для многопроцессорных устройств, доступ к внешним устр-вам

 

•управление устройствами и ФС

 

Планирование.

Будем считать, что рассматриваем некоторую модельную ОС, в которой процесс после его формирования поступает на буфер ввода процесса. За время нахождения в буфере формируются данные и структуры для выполнения. Буфер обрабатываемых процессов внешней памяти, в которой находится программа, обрабатывается в мультипрограммном режиме.

 

Обобщенный жизненный цикл процесса:

       
   
 
 

 

       
   
 
 

 


 

 

Но это только самые явные этапы планирования.

 

 

Типы ОС

 

Многое определяется стратегиями планирования в данных ОС. С точки зрения типов ОС планирования традиционно выделяют 3 типа:

1) Пакетная ОС

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

Первоначально на перфокартах, позже в буфере ввода программ.

 

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

 

lВыполнение процесса завершено

lВозникло прерывание

lБыл фиксирован факт зацикливания процесса

 

Примитивная, но критический эффект – минимизация накладных расходов.

 

2) Система разделения времени

Базируется на квантировании времени. Квант времени ЦП некоторый фиксированный ОС промежуток времени работы ЦП.

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

 

lИсчерпался выделенный квант времени

 

lВыполнение процесса завершено

 

lВозникло прерывание

 

lБыл фиксирован факт зацикливания процесса

варьируя размер кванта, можно добиться разных результатов.

 

3) ОС реального времени

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

Обычно обеспечивают управление техническим оборудованием.

Примером такой организации планирования ЦП может быть следующая схема. Планировщик построен на двухуровневой схеме. Мы считаем, что множество задач может содержать, предположим, счетные задачи и интерактивные задачи. Первый уровень определяет приоритет между двумя классами задач и либо отдает ЦП сначала счетной задаче, либо интерактивной задаче. А второй уровень определяет то, о чем мы говорили перед этим, т.е. как выбрать задачу в пределах одного класса и как ее прервать. Такая смешанная система может работать следующим образом. Первый уровень планирования будет работать по такому принципу: если в данный момент нет ни одной интерактивной задачи, готовой к выполнению (а это вполне реальная ситуация, если пользователи занимаются редактированием текста), то ЦП передается счетным задачам, но добавляется одно условие: как только появляется хотя бы одна интерактивная задача, счетная задача прерывается и управление передается блоку интерактивных задач.

 

Типы процессов.

 

 

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

«Легковесные процессы» - нити - работают в мультипрограммном режиме одновременно с активировавшей их задачей и используют ее виртуальное адресное пространство.

 

 

Также процессы можно классифицировать как процессы с однонитевой организацией и с многонитевой.

 

 
 


однонитевой процесс многонитевый процесс

 

 

Понятие процесса можно определить несколькими способами. Как исполняемый код;

 

собственное адресное пространство, которое представляет собой совокупность виртуальных адресов, которые может использовать процесс;

ресурсы системы, которые назначены процессу ОС;

хотя бы одна выполняемая нить.

Одна из основных характеристик процесса – контекст – совокупность данных, характеризующих актуальное состояние процесса. Контекст включает в себя 2 составляющие:

1) Пользовательская составляющая – текущее состояние программы (совокупность машинных команд, размещенных в ОЗУ)

2) Системная составляющая

– информация идентификационного характера (PID процесса, PID «родителя»…)

– информация о содержимом регистров (РОН, индексные регистры, флаги...)

– информация, необходимая для управления процессом (состояние процесса, приоритет....)

Процессы в ОС UNIX.

Процесс в UNIXe имеет системно-ориентированные характеристики:

Объект, зарегистрированный в таблице процессов

Объект, порожденный системным вызовом fork().

Каждому процессу соответствует идентификатор процесса, который идентифицируется с процессом до его завершения.

Контекст процесса в UNIXе – совокупность данных, которые принадлежат адресному пространству процесса и ОС, состоит из 3х компонент:

пользовательская

аппаратная

 

системная

 

 

1)Пользовательская:

 

Сегмент кода

машинные компоненты

системные команды

 

 

Сегмент данных

 

 

статические данные

разделяемая память

стек

2) Аппаратная составляющая - все регистры и аппаратные таблицы ЦП, используемые активным или исполняемым процессом

•счетчик команд

• регистр состояния процессора

• аппарат виртуальной памяти

• регистры общего назначения

• и т. д.

 

3) Системная составляющая:

 

•приоритет процесса

•реальный и эффективный идентификаторы пользователя-владельца

•текущее состояние процесса

•реальный и эффективный идентификатор группы, к которой принадлежит владелец

•идентификатор родительского процесса

 

Создание нового процесса.

#include <sys/types.h>

#include <unistd.h>

 

pid_t fork(void);

 

Системный вызов fork()

С понятием процесса в ОС UNIX связаны средства формирования процесса, суть их заключается в следующем. Ядром системы поддерживается функция fork(). При обращении к этой функции происходит дублирование процесса. Образуется процесс-двойник, который идентичен процессу-отцу (идентичен, но не совпадает с процессом-отцом!). Функция возвращает значение:

>0, это PID сыновнего процесса (мы находимся в процессе-отце)

=0 (мы находимся в процессе-сыне)

=-1 произошла ошибка - невозможно создать новый процесс, эта ошибка может возникнуть при недостатке места в таблице процессов, при нехватке места в системных областях данных и т.п.

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

· Окружение - при формировании процесса ему передается некоторый набор параметров-переменных, используя которые, процесс может взаимодействовать с операционным окружением (интерпретатором команд и т.д.). О переменных окружения мы поговорим на последних лекциях нашего курса;

· Файлы, открытые в процессе-отце, за исключением тех, которым было запрещено передаваться процессам-потомкам с помощью задания специального параметра при открытии. Речь идет о том, что в системе при открытии файла с файлом ассоциируется некоторый атрибут, который определяет правила передачи этого открытого файла сыновним процессам. По умолчанию открытые в «отце» файлы можно передавать «потомкам», но можно изменить значение этого параметра и блокировать передачу открытых в процессе-отце файлов.);

· Способы обработки сигналов;

· Разрешение переустановки действующего идентификатора пользователя (это то, что связано с s-bit’ом);

· В ОС имеется возможность системными вызовами осуществлять отладку (профилирование) программы, в процессе может быть указано - разрешено или нет профилирование;

· Разделяемые ресурсы процесса-отца;

· Текущий рабочий каталог и домашний каталоги.

Не наследуется при создании нового процесса идентификатор процесса

 

В качестве иллюстрации работы fork() можно привести следующую картинку:

 

 

Здесь процесс с PID=105 создается процессом с PID=101.

Также следует отметить, что если убивается процесс-отец, то новым отцом становится 1-ый процесс ОС.

 

 

Пример:

int main(int argc, char **argv)

 

{

 

printf("PID=%d; PPID=%d \n", getpid(),

getppid());

 

fork();

printf("PID=%d; PPID=%d \n", getpid(),

getppid());

}

 

Системный вызов exec()

#include <unistd.h>

int execl(const char *path, char *arg0, …, char *argn, 0);

 

Суть функций exec() - в следующем: при обращении к ней происходит замена тела текущего процесса, в соответствии с именем исполняемого файла, указанного одним из параметров функции. Загружается новый процесс и управление перелается на точку входа. Функция возвращает «-1», если действие не выполнено, и код, отличный от «-1», если операция прошла успешно.

 

В результате exec() изменяется:

режим обработки сигналов;

эффект идентификации владельца;

файловые дескрипторы.

 

Пример:

#include <unistd.h>

 

int main(int argc, char **argv)

 

{

 

/*тело программы*/

 

execl(“/bin/ls”,”ls”,”-l”,(char*)0);

/* или execlp(“ls”,”ls”, ”-l”,(char*)0);*/

printf(“это напечатается в случае неудачного обращения к предыдущей функции, к примеру, если не был найден файл ls \n”);

}

 

 

Работа с функциями fork – exec.

Связка fork/exec по своей мощности сильнее, чем, если бы была единая функция, которая сразу бы создавала новый процесс и замещала бы его содержимое. Fork/exec позволяют вставить между ними еще некоторую программу, которая будет содержать какие-то полезные действия. Может возникнуть естественный вопрос: зачем все это нужно? ОС UNIX - конструктор. Система может конструировать сложные объекты за счет функциональных «кирпичиков». Так вот эти кирпичики - это функции fork(), exec(...) и др.

 

Причинами завершения процесса могут быть:

 

системный вызов _exit()

оператора return, входящего в состав функции main()

получение некоторых сигналов

 

Пример:

 

int main(int argc, char **argv)

 

{

 

if(fork() == 0)

{

 

execl(“/bin/echo”,”echo”,”это”,”сообщение один”,NULL);

printf(“ошибка”);

 

}

 

if(fork() == 0)

{

execl(“/bin/echo”,”echo”,”это”,”сообщение два”,NULL);

printf(“ошибка”);

 

}

 

if(fork() == 0)

 

{

execl(“/bin/echo”,”echo”,”это”,”сообщение три”,NULL);

printf(“ошибка”);

}

printf(“процесс-предок закончился”)

}

 

Для завершения выполнения процесса предназначен системный вызов _exit()

 

void _exit(int exitcode);

 

Этот вызов никогда не завершается неудачно, поэтому для него не предусмотрено возвращающего значения. С помощью параметра status процесс может передать породившему его процессу информацию о статусе своего завершения. Принято, хотя и не является обязательным правилом, чтобы процесс возвращал нулевое значение при нормальном завершении, и ненулевое – в случае какой-либо ошибки или нештатной ситуации.

 

 

В любом из этих случаев происходит следующее:

- освобождаются сегмент кода и сегмент данных процесса

- закрываются все открытые дескрипторы файлов

- если у процесса имеются потомки, их предком назначается процесс с идентификатором 1

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

процессу-предку завершаемого процесса посылается сигнал SIGCHLD

Процесс-предок имеет возможность получить информацию о завершении своего потомка. Для этого служит системный вызов wait():

pid_t wait(int *status);

 

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

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

Если к моменту вызова wait() один из потомков данного процесса уже завершился, перейдя в состояние зомби, то выполнение родительского процесса не блокируется, и wait() сразу же возвращает информацию об этом завершенном процессе. Если же к моменту вызова wait() у процесса нет потомков, системный вызов сразу же вернет –1. Также возможен аналогичный возврат из этого вызова, если его выполнение будет прервано поступившим сигналом.

 

 

Жизненный цикл процесса может быть изображен следующим образом:

1. Процесс только что создан посредством вызова fork().

2. Процесс находится в очереди готовых на выполнение процессов.

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

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

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

6. Процесс осуществил вызов exit() или получил сигнал на завершение. Ядро освобождает ресурсы, связанные с процессом, кроме кода возврата и статистики выполнения. Далее процесс переходит в состоянии зомби, а затем уничтожается.

 

 


 

 

Последовательность действий при загрузке UNIXа.

1) загрузка ядра системы, а основную память и ее запуск. Наличие системного устройства – устр-ва, на котором аппаратура ищет ОС при старте

1.Аппаратный загрузчик читает нулевой блок системного устройства.

2.После чтения этой программы она выполняется, т.е. ищется и считывается в память файл /UNIX, расположенный в корневом каталоге и который содержит код ядра системы.

3.Запускается на исполнение этот файл.

 

 

2) инициализация системы включает в себя:

 

1. устанавливаются системные часы (для генерации прерываний),

 

2. формируется диспетчер памяти,

 

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

 

4. По окончании этих действий происходит инициализация процесса с номером "0".

Для этого невозможно использовать методы порождения процессов, изложенные выше, т.е. с использованием функций fork() и exec().

При инициализации этого процесса резервируется память под его контекст и формируется нулевая запись в таблице процессов.

Основными отличиями нулевого процесса являются следующие моменты

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

2. Он существует в течениее всего времени работы системы (чисто системный процесс) и считается, что он активен, когда работает ядро ОС.

 

Далее ядро копирует "0" процесс и создает "1" процесс.

Сначала процесс "1" представляет собой полную копию процесса "0", т.е. у него нет области кода. Потом происходит увеличение его размера. Во вновь созданную кодовую область копируется программа, реализующая системный вызов exec(), необходимый для выполнения программы /etc/init.

На этом завершается подготовка первых двух процессов.

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

Второй – это уже подобие реального процесса.

 

Далее ОС переходит к выполнению программ диспетчера.

Диспетчер наделен обычными функциями и на первом этапе он запускает exec(), который заменит команды процесса "1" кодом, содержащимся в файле /etc/init. Получившийся процесс, называемый init, призван настраивать структуры процессов системы.

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

 

При выходе из однопользовательского режима init создает многопользовательскую среду.

С этой целью init организует процесс getty для каждого активного канала связи, т.е. каждого терминала. Это программа ожидает входа кого-либо по каналу связи.

 

 

init организует процесс getty для каждого активного канала связи, т.е. каждого терминала. Это программа ожидает входа кого-либо по каналу связи.

Далее, используя системный вызов exec(), getty передает управление программе login, проверяющей пароль.

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

Таким образом, процесс init поддерживает многопользовательскую структуру во время функционирования системы.

 

3)

 

Лекция 5. Взаимодействие процессов: синхронизация, тупики

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

Совместное использование несколькими процессами ресурса ВС, когда каждый из процессов одновременно владеет ресурсом называют разделением ресурса. Разделению подлежат как аппаратные, так программные ресурсы. Разделяемые ресурсы, которые должны быть доступны в текущий момент времени только одному процессу – это так называемые критические ресурсы. Таковыми ресурсами могут быть, как внешнее устройство, так и некая переменная, значение которой может изменяться разными процессами.

Необходимо уметь решать две важнейшие задачи:

1. Распределение ресурсов между процессами.

2. Организация защиты адресного пространства и других ресурсов, выделенных определенному процессу, от неконтролируемого доступа со стороны других процессов.

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

Рассмотрим ситуацию, изображенную на Рис. 1:

Рис. 1 Конкуренция процессов за ресурс.

В этом случае символ, считанный процессом А, был потерян, а символ, считанный процессом В, был выведен дважды. Результат выполнения процессов здесь зависит от того, в какой момент осуществляется переключение процессов, и от того, какой конкретно процесс будет выбран для выполнения следующим. Такие ситуации называются гонками (race conditions) между процессами, а процессы – конкурирующими. Единственный способ избежать гонок при использовании разделяемых ресурсов – контролировать доступ к любым разделяемым ресурсам в системе. При этом необходимо организовать взаимное исключение – т.е. такой способ работы с разделяемым ресурсом, при котором постулируется, что в тот момент, когда один из процессов работает с разделяемым ресурсом, все остальные процессы не могут иметь к нему доступ.

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

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

При организации взаимного исключения могут возникнуть тупики (deadlocks), ситуации в которой конкурирующие за критический ресурс процессы вступают в клинч – безвозвратно блокируются.

 

Есть два процесса А и В, каждому из которых в некоторый момент требуется иметь доступ к двум ресурсам R1 и R2. Процесс А получил доступ к ресурсу R1 , и следовательно, никакой другой процесс не может иметь к нему доступ, пока процесс А не закончит с ним работать. Одновременно процесс В завладел ресурсом R2. В этой ситуации каждый из процессов ожидает освобождения недостающего ресурса, но оба ресурса никогда не будут освобождены, и процессы никогда не смогут выполнить необходимые действия.

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

 

Рассмотри классические методы (средства) синхронизации

 

Средства синхронизации

Семафоры Дейкстры

 

Семафоры были предложены как механизм синхронизации доступа к разделяемым ресурсам западноевропейским ученым Дейкстрой (Дийкстра - и такой вариант его имени встречается в литературе), человеком известным в теории программирования (Кстати, именно его учения легли в основу разработок алгоритмов маршрутизации сетей). В литературе эти семафоры часто называют семафорами Дейкстры. Он предложил использовать некий формализм, суть которого заключается в том, что есть некоторая целочисленная переменная S, которая называется семафором. Над семафором определены две операции: P(S), V(S).

· действие P(S) таково: если значение семафора равно нулю, то процесс, выполняющий обращение к P(S) будет приостановлен до тех пор, пока какой-нибудь другой процесс не изменит значение семафора, если же значение семафора отлично от 0, то значение семафора будет уменьшено на единицу.

· V(S) увеличивает значение семафора на единицу;

Считается, что операции P(S) и V(S) неделимы. Это означает, что выполнение этих операций не может прерваться до их завершения. Эти операции состоят как бы из трех команд: чтение переменной S, сравнение с 0 и то или иное действие над S. Так вот эти три команды, три действия неделимы. Никакое событие не может приостановить выполнение этой цепочки действий и передать управление другому процессу. (Прослеживается некоторая аналогия с механизмом прерываний, т.е. если при выполнении команды произошло прерывание, то команда выполнятся до конца, затем происходит обработка прерывания с последующим возвратом в эту же точку программы). Две операции с семафором - как бы две цельные машинные команды. Эти команды должны входить в систему команд или же ОС должна уметь эмулировать их.

Частным случаем продекларированного семафора является двоичный семафор, максимальное значение которого равно единичке. Если S=1, то это означает, что ни один из процессов (связанных с этим семафором) не находится в критическом участке. При S=0 один из процессов находится в критическом участке {вот-вот попадет в очередь}, а другой нормально функционирует. При S=-1 один из процессов находится в критическом участке, а другой заблокирован и находится в очереди.

На самом деле двоичные семафоры наиболее часто находили применение в аппаратных реализациях, например, в многомашинных комплексах с общей оперативной памятью. Аналогичным образом можно говорить и о т. н. k-ичных семафорах.

 

 

Использование двоичного семафора для организации взаимного исключения проиллюстрировано на рисунке.

 

 

 

Семафоры – это низкоуровневые средства синхронизации, для корректной практической реализации которых необходимо наличие специальных, атомарных семафорных машинных команд.

 

Мониторы

Идея монитора была впервые сформулирована в 1974 г. Хоаром. В отличие от других средств, монитор представляет собой языковую конструкцию, т. е. Некоторое средство, предоставляемое языком программирования и поддерживаемое компилятором. Монитор представляет собой совокупность процедур и структур данных, объединенных в программный модуль специального типа. Постулируются три основных свойства монитора:

1. структуры данных, входящие в монитор, могут быть доступны только для процедур, входящих в этот монитор (таким образом, монитор представляет собой некоторый аналог объекта в объектно-ориентированных языках и реализует инкапсуляцию данных);

  1. процесс «входит» в монитор путем вызова одной из его процедур;
  2. в любой момент времени внутри монитора может находиться не более одного процесса. Если процесс пытается попасть в монитор, в котором уже находится другой процесс, он блокируется. Таким образом, чтобы защитить разделяемые структуры данных, из достаточно поместить внутрь монитора вместе с процедурами, представляющими критические секции для их обработки.

 

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

 

 

Обмен сообщениями

 

Средство, решающее проблему синхронизации

•для однопроцессорных систем и систем с общей памятью,

•для распределенных систем (когда каждый процессор имеет доступ только к своей памяти)

 

 

Основная функциональность метода обеспечивается двумя примитивами (являющимися, как и семафоры, в отличие от мониторов, системными вызовами, а не конструкциями языка):

 

send (destination, message)

receive (message)

 

•Синхронизация

- Операции посылки/приема сообщения могут быть блокирующими и не блокирующими.

• Адресация

-Прямая (ID процесса)

-Косвенная (почтовый ящик, или очередь сообщений)

• Длина сообщения

Классические задачи синхронизации процессов

«Обедающие философы»

Пять философов собираются за круглым столом, перед каждым из них стоит блюдо со спагетти, и между каждыми двумя соседями лежит вилка. Каждый из философов некоторое время размышляет, затем берет две вилки (одну в правую руку, другую в левую) и ест спагетти, затем опять размышляет и так далее. Каждый из них ведет себя незави

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...