- •Челябинск
- •2002 Предисловие
- •От издательства
- •Часть 1 Операционные системы и среды
- •Глава 1 Основные понятия Понятие операционной среды
- •Понятия вычислительного процесса и ресурса
- •Диаграмма состояний процесса
- •Реализация понятия последовательного процесса в ос
- •Процессы и треды
- •Прерывания
- •Основные виды ресурсов
- •Классификация операционных систем
- •Контрольные вопросы и задачи Вопросы для проверки
- •Глава 2 Управление задачами и памятью в операционных системах
- •Планирование и диспетчеризация процессов и задач Стратегии планирования
- •Дисциплины диспетчеризации
- •Вытесняющие и не вытесняющие алгоритмы диспетчеризации
- •Качество диспетчеризации и гарантии обслуживания
- •Диспетчеризация задач с использованием динамических приоритетов
- •Память и отображения, виртуальное адресное пространство
- •Простое непрерывное распределение и распределение с перекрытием (оверлейные структуры)
- •Распределение статическими и динамическими разделами
- •Разделы с фиксированными границами
- •Разделы с подвижными границами
- •Сегментная, страничная и сегментно-страничная организация памяти
- •Сегментный способ организации виртуальной памяти
- •Страничный способ организации виртуальной памяти
- •Сегментно-страничный способ организации виртуальной памяти
- •Распределение оперативной памяти в современных ос для пк
- •Распределение оперативной памяти вMs-dos
- •Распределение оперативной памяти вMicrosoftWindows95/98
- •Распределение оперативной памяти вMicrosoftWindowsNt
- •Контрольные вопросы и задачи Вопросы для проверки
- •Глава 3 Особенности архитектуры микропроцессоровi80x86
- •Реальный и защищённый режимы работы процессора
- •Новые системные регистры микропроцессоров i80x86
- •Адресация в 32-разрядных микропроцессорахi80х86 при работе в защищённом режиме Поддержка сегментного способа организации виртуальной памяти
- •Поддержка страничного способа организации виртуальной памяти
- •Режим виртуальных машин для исполнения приложений реального режима
- •Защита адресного пространства задач
- •Уровни привилегий для защиты адресного пространства задач
- •Механизм шлюзов для передачи управления на сегменты кода с другими уровнями привилегий
- •Система прерываний 32-разрядных микропроцессоровi80x86
- •Работа системы прерываний в реальном режиме работы процессора
- •Работа системы прерываний в защищённом режиме работы процессора
- •Обработка прерываний в контексте текущей задачи
- •Обработка прерываний с переключением на новую задачу
- •Контрольные вопросы и задачи Вопросы для проверки
- •Глава 4 Управление вводом/выводом и файловые системы
- •Основные понятия и концепции организации ввода/вывода в ос
- •Режимы управления вводом/выводом
- •Закрепление устройств, общие устройства ввода/вывода
- •Основные системные таблицы ввода/вывода
- •Синхронный и асинхронный ввод/вывод
- •Кэширование операций ввода/вывода при работе с накопителями на магнитных дисках
- •Функции файловой системы ос и иерархия данных
- •Структура магнитного диска (разбиение дисков на разделы)
- •Файловая системаFat
- •Структура загрузочной записиDos
- •Файловые системыVfaTиFat32
- •Файловая система hpfs
- •Файловая система ntfs (New Technology File System)
- •Основные возможности файловой системы ntfs
- •Структура тома с файловой системой ntfs
- •Возможности файловой системыNtfSпо ограничению доступа к файлам и каталогам
- •Основные отличияFaTи ntfs
- •Контрольные вопросы и задачи Вопросы для проверки
- •Задания
- •Глава 5 Архитектура операционных систем и интерфейсы прикладного
- •Принцип функциональной избирательности
- •Принцип генерируемости ос
- •Принцип функциональной избыточности
- •Принцип виртуализации
- •Принцип независимости программ от внешних устройств
- •Принцип совместимости
- •Принцип открытой и наращиваемой ос
- •Принцип мобильности (переносимости)
- •Принцип обеспечения безопасности вычислений
- •Микроядерные операционные системы
- •Монолитные операционные системы
- •Требования, предъявляемые к ос реального времени
- •Мультипрограммность и многозадачность
- •Приоритеты задач (потоков)
- •Наследование приоритетов
- •Синхронизация процессов и задач
- •Предсказуемость
- •Принципы построения интерфейсов операционных систем
- •Интерфейс прикладного программирования
- •Реализация функцийApIна уровне ос
- •Реализация функцийApIна уровне системы программирования
- •Реализация функцийApIс помощью внешних библиотек
- •Платформенно-независимый интерфейс posix
- •Пример программирования в различныхApiос
- •Текст программы дляWindows(WinApi)
- •Текст программы дляLinux(posixapi)
- •Контрольные вопросы и задачи Вопросы для проверки
- •Глава 6 Проектирование параллельных взаимодействующих вычислительных процессов
- •Независимые и взаимодействующие вычислительные процессы
- •Средства синхронизации и связи при проектировании взаимодействующих вычислительных процессов
- •Использование блокировки памяти при синхронизации параллельных процессов
- •Возможные проблемы при организации взаимного исключения посредством использования только блокировки памяти
- •Алгоритм Деккера
- •Синхронизация процессов посредством операции «проверка и установка»
- •Семафорные примитивы Дейкстры
- •Мьютексы
- •Использование семафоров при проектировании взаимодействующих вычислительных процессов
- •Задача «поставщик – потребитель»
- •Пример простейшей синхронизации взаимодействующих процессов
- •Решение задачи «читатели – писатели»
- •Мониторы Хоара
- •Почтовые ящики
- •Конвейеры и очереди сообщений Конвейеры (программные каналы)
- •Очереди сообщений
- •Примеры создания параллельных взаимодействующих вычислительных процессов
- •Пример создания многозадачного приложения с помощью системы программированияBorlandDelphi
- •Пример создания комплекса параллельных взаимодействующих программ, выступающих как самостоятельные вычислительные процессы
- •Контрольные вопросы и задачи Вопросы для проверки
- •Глава 7 Проблема тупиков и методы борьбы с ними
- •Понятие тупиковой ситуации при выполнении параллельных вычислительных процессов
- •Примеры тупиковых ситуаций и причины их возникновения
- •Пример тупика на ресурсах типаCr
- •Пример тупика на ресурсах типаCRиSr
- •Пример тупика на ресурсах типаSr
- •1: P(s2); 5: p(s1);
- •Формальные модели для изучения проблемы тупиковых ситуаций
- •Сети Петри
- •Вычислительные схемы
- •Модель пространства состояний системы
- •Методы борьбы с тупиками
- •Предотвращение тупиков
- •Обход тупиков
- •Обнаружение тупика
- •Обнаружение тупика посредством редукции графа повторно используемых ресурсов
- •Методы обнаружения тупика по наличию замкнутой цепочки запросов
- •Алгоритм обнаружения тупика по наличию замкнутой цепочки запросов
- •Контрольные вопросы и задачи Вопросы для проверки
- •Глава 8 Современные операционные системы
- •Семейство операционных системUnix Общая характеристика семейства операционных систем unix, особенности архитектуры семейства осunix
- •Основные понятия системыUnix
- •Виртуальная машина
- •Пользователь
- •Интерфейс пользователя
- •Привилегированный пользователь
- •Команды и командный интерпретатор
- •Процессы
- •Функционирование системыUnix
- •Выполнение процессов
- •Подсистема ввода/вывода
- •Перенаправление ввода/вывода
- •Файловая система
- •Структура файловой системы
- •Защита файлов
- •Межпроцессные коммуникации вUnix
- •Сигналы
- •Семафоры
- •Программные каналы
- •Очереди сообщений
- •Разделяемая память
- •Вызовы удаленных процедур (rpc)
- •Операционная системаLinux
- •Семейство операционных систем os/2WarpкомпанииIbm
- •Особенности архитектуры и основные возможности os/2Warp
- •Особенности интерфейса os/2Warp
- •Серверная операционная система os/2Warp4.5
- •Сетевая ос реального времениQnx
- •Архитектура системыQnx
- •Основные механизмы qnx для организации распредёленных вычислений
- •Контрольные вопросы и задачи Вопросы для проверки
- •Приложение а Тексты программы параллельных взаимодействующих задач
- •Приложение б Тексты программ комплекса параллельных взаимодействующих приложений
- •Текст программы а
- •Текст программы в
- •Текст программы d
- •Текст программы g
- •Список литературы
- •Часть 1 6
- •Глава 5 Архитектура операционных систем и интерфейсы прикладного 240
- •Глава 6 Проектирование параллельных взаимодействующих вычислительных 279
- •Глава 7 Проблема тупиков и методы 348
- •Глава 8 Современные операционные 391
Семафорные примитивы Дейкстры
Понятие семафорных механизмов было введено Дейкстрой [27]. Семафор –переменная специального типа, которая доступна параллельным процессам для проведения над ней только двух операций: «закрытия» и «открытия», названных соответственно Р- и V-операциями. Эти операции являются примитивами относительно семафора, который указывается в качестве параметра операций. Здесь семафор выполняет роль вспомогательного критического ресурса, так как операции Р и V неделимы при своём выполнении и взаимно исключают друг друга.
Семафорный механизм работает по схеме, в которой сначала исследуется состояние критического ресурса, идентифицируемое значением семафора, а затем уже осуществляется допуск к критическому ресурсу или отказ от него на некоторое время. При отказе доступа к критическому ресурсу используется режим «пассивного ожидания». Поэтому в состав механизма включаются средства формирования и обслуживания очереди ожидающих процессов. Эти средства реализуются супервизором операционной системы. Необходимо отметить, что в силу взаимного исключения примитивов попытка в различных параллельных процессах одновременно выполнить примитив над одним и тем же семафором приведет к тому, что она будет успешной только для одного процесса. Все остальные процессы будут взаимно исключены на время выполнения примитива. Основным достоинством использования семафорных операций является отсутствие состояния «активного ожидания», что может существенно повысить эффективность работы мультипрограммной вычислительной системы.
В настоящее время на практике используется много различных видов семафорных механизмов [75]. Варьируемыми параметрами, которые отличают различные виды примитивов, являются начальное значение и диапазон изменения значений семафора, логика действий семафорных операций, количество семафоров, доступных для обработки при исполнении отдельного примитива.
Обобщенный смысл примитива P(S)1состоит в проверке текущего значения семафораS, и если оно не меньше нуля, то осуществляется переход к следующей за примитивом операции. В противном случае процесс снимается на некоторое время с выполнения и переводится в состояние «пассивного ожидания». Находясь в списке заблокированных, ожидающий процесс не проверяет семафор непрерывно, как в случае активного ожидания. Вместо него на процессоре может исполняться другой процесс, который реально совершает полезную работу.
Операция V(S)2связана с увеличением значения семафора на единицу и переводом одного или нескольких процессов в состояние готовности к центральному процессору.
Отметим еще раз, что операции Р и V выполняются операционной системой в ответ на запрос, выданный некоторым процессом и содержащий имя семафора в качестве параметра.
Рассмотрим первый вариант алгоритма работы семафорных операций, который представлен в листинге 6.7.
Допустимыми значениями семафоров являются только целые числа. Двоичным семафором будем называть семафор, максимально возможное значение которого будет равно единице. В противном случае семафоры называют N-ичными. Есть реализации, в которых семафорные переменные не могут быть отрицательными, а есть и такие, где отрицательное значение указывает на длину очереди процессов, стоящих в состоянии ожидания открытия семафора.
Листинг 6.7.Вариант реализации семафорных примитивов
P(S):S:=S-1;
ifS<0then
{ остановить процесс и поместить его в очередь ожидания к семафору S }
V(s):ifS<0then
{поместить один из ожидающих процессов очереди семафора S в очередь
готовности};
S:=S+1
Заметим, что для работы с семафорными переменными необходимо еще иметь операцию инициализации самого семафора, то есть операцию задания ему начального значения. Обычно эту операцию называют InitSem; как правило, она имеет два параметра – имя семафорной переменной и её начальное значение; следовательно, обращение к ней имеет вид:
ImtSem (Имя_семафора, Начальное_значение_семафора);
Попытаемся на нашем примере двух конкурирующих процессов ПР1 и ПР2 проанализировать использование данных семафорных примитивов для решения проблемы критического интервала. Программа, иллюстрирующая это решение, представлена в листинге 6.8.
Листинг 6.8.Взаимное исключение с помощью семафорных операций
var S:semafor;
begin InitSem(S,1);
parbegin
ПР1: while true do
begin
P(S);
CS1 { Критический интервал процесса ПР1 }
V(S)
end
and
ПР2: while true do
begin
P(S);
CS2 { Критический интервал процесса ПР2 }
V(S)
end
parend
end.
Семафор Sимеет начальное значение, равное1. Если процессыПР1и ПР2 попытаются одновременно выполнить примитивP(S), то это удастся успешно сделать только одному из них. Предположим, это сделал процессПР2, тогда он закрывает семафорS, после чего выполняется его критический интервал. ПроцессПР1в рассматриваемой ситуации будет заблокирован на семафореS. Тем самым будет гарантировано взаимное исключение.
После выполнения примитива V(S)процессомПР2семафорSоткрывается, указывая на возможность захвата каким-либо процессом освободившегося критического ресурса. При этом производится перевод процессаПР1из заблокированного состояния в состояние готовности.
На уровне реализации возможно одно из двух решений в отношении процессов, которые переводятся из очереди ожидания в очередь готовности при выполнении примитива V:
процесс при его активизации (выборка из очереди готовности) вновь пытается выполнить примитив Р, считая предыдущую попытку неуспешной;
процесс при помещении его и очередь готовности отмечается как успешно выполнивший примитив Р. Тогда при его активизации управление будет передано не на повторное выполнение примитиваР, а на команду, следующую за ним. Рассмотрим первый способ реализации. Пусть процессПР2в некоторый момент времени выполняет операциюP(S).Тогда семафорSстановится равным нулю. Пусть далее процессПР1пытается выполнить операциюP(S).ПроцессПР1в этом случае «засыпает» на семафореS, так как значение семафораSравнялось нулю, а теперь станет равным(-1). После выполнения критического интервала процессПР2выполняет операцию V(S),при этом значение семафораSстановится равным нулю, а процессПР1переводится в очередь готовности. Пусть через некоторое время процессПР1будет активизирован, то есть выведен из состояния ожидания, и сможет продолжить своё исполнение. Он повторно пытается выполнить операцию P(S),однако это ему не удается, так как S=0.ПроцессПР1«засыпает» на семафоре, а его значение становится равным(-1).Если через некоторое время процессПР2попытается выполнитьP(S), то он тоже «уснет». Таким образом, возникнет так называемая тупиковая ситуация, так как «будить» процессыПР1иПР2некому.
При втором способе реализации тупиковой ситуации не будет. Действительно, пусть всё происходит также до момента окончания исполнения процессом ПР2примитиваV(S). Пусть примитивV(S)выполнен иS=0. Через некоторое время процессПР1активизировался. Согласно данному способу реализации, он сразу же попадёт в свой критический интервал. При этом никакой другой процесс не попадёт в свой критический интервал, так как семафор остался закрытым. После исполнения своего критического интервала процессПР1выполнитV(S).Если за время выполнения критического интервала процессаПР1процессПР2не делал попыток выполнить операциюP(S),семафорSустановится в единицу. В противном случае значение семафора будет не больше нуля. Но в любом варианте после завершения операцииV(S)процессомПР1доступ к критическому ресурсу со стороны процессаПР2будет разрешен.
Заметим, что возникновение тупиков возможно в случае несогласованного выбора механизма реактивации процессов из очереди, с одной стороны, и выбора алгоритмов семафорных операций – с другой.
Возможен другой алгоритм работы семафорных операций:
P(S): if S>=1 then S:=S-1
else WAIT(S)
{остановить процесс и поместить в очередь ожидания к семафору S}
V(S): if S<0 then RELEASE(S)
{поместить один из ожидающих процессов очереди семафора S
в очередь готовности};
S:-S+1.
Здесь вызов WAIT(S)означает, что супервизор ОС должен перевести задачу в состояние ожидания, причём очередь процессов связана с семафоромS. ВызовRELEASE(S)означает обращение к диспетчеру задач с просьбой перевести первый из процессов, стоящих в очередиS, в состояние готовности к исполнению.
Использование семафорных операций, выполненных подобным образом, позволяет решать проблему критических интервалов на основе первого способа реализации без вероятности возникновения тупиков. Действительно, пусть ПР2в некоторый момент времени выполнит операцию P(S).Тогда семафорSстановится равным нулю. Пусть далее процессПР1пытается выполнить операциюP(S). ПроцессПР1в этом случае «заснет» на семафореS, так какS=0, причём значениеSне изменится. После выполнения своего критического интервала процессПР2 выполнит операцию V(S),при этом значение семафораSстанет равный единице, а процессПР1переведётся в очередь готовности. Если через некоторое время процессПР1будет активизирован, он успешно выполнитP(S) и войдёт в свой критический интервал.
В однопроцессорной вычислительной системе неделимость Р-иV-операций можно обеспечить с помощью простого запрета прерываний. Сам же семафорS можно реализовать в виде записи с двумя полями (листинг 6.9). В одном поле хранится целое значениеS, во втором – указатель на список процессов, заблокированных на семафореS.
Листинг6.9.РеализацияР-иV-операций для однопроцессорной системы
type Semaphore = record
счетчик :integer;
указатель :pointer;
end;
var S :Semaphore;
procedure P ( var S : Semaphore);
begin ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ;
S.счетчик:= S-счетчик-1;
if S.счетчик < 0 then
WAIT(S); {ВСТАВИТЬ ОБРАТИВШИЙСЯ ПРОЦЕСС В
СПИСОК ПО S.указатель и УСТАНОВИТЬ НА
ПРОЦЕССОР ГОТОВЫЙ К ВЫПОЛНЕНИЮ
ПРОЦЕСС }
РАЗРЕШИТЬ__ПРЕРЫВАНИЯ
end;
procedure V ( var S : Semaphore);
begin ЗАПРЕТИТЬ ПРЕРЫВАНИЯ;
S.счетчик:=S.счетчик+1;
if S.счетчик <= 0 then
RELEASE (S); { ДЕБЛОКИРОВАТЬ ПЕРВЫЙ ПРОЦЕСС ИЗ
СПИСКА ПО S.указатель }
РАЗРЕШИТЬ_ПРЕРЫВАНИЯ
end;
procedure InitSem (var S : Semaphore);
begin
S.счетчик:=1;
S.указатель:=nil;
end;
Реализация семафоров в мультипроцессорных системах более сложна, чем в однопроцессорных. Одновременный доступ к семафору S двух процессов, выполняющихся на однопроцессорной вычислительной системе, предотвращается запретом прерываний. Однако этот механизм не подходит для мультипроцессорных систем, так как он не препятствует двум или более процессам одновременно обращаться к одному семафору. В силу того, что такой доступ должен реализовываться как критический интервал, необходимо дополнительное аппаратное взаимное исключение доступа для различных процессоров. Одним из решений является использование уже знакомых нам неделимых команд типа «ПРОВЕРКА И УСТАНОВКА» (TS). Двухкомпонентный семафор в этом случае расширяется включением третьего компонента – логического признакаВзаимоИскл(листинг 6.10).
Листинг 6.10.Реализация Р- и V-операций для мультипроцессорной системы
type Semaphore = record
счетчик : integer;
указатель : pointer;
взаимоискл : boolean;
end;
var S : Semaphore;
procedure InitSem (var S : Semaphore);
begin
With S do
begin
счетчик:=1;
указатель :=nil;
взаимоискл:=true;
end;
end;
procedure P ( var S : Semaphore);
var разрешено : boolean;
begin
ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ;
repeat TS(разрешено, S.взаимоискл) until разрешено;
S. счетчик:= счетчик-1;
if S.счетчик < 0 then WAIT(S); { ВСТАВИТЬ ОБРАТИВШИЙСЯ
ПРОЦЕСС В СПИСОК
ПО S.указатель И УСТАНОВИТЬ
НА CPU ГОТОВЫЙ ПРОЦЕСС }
S.взаимоискл:=true;
РАЗРЕШИТЬ_ПРЕРЫВАНИЯ
end;
procedure V ( var S : Semaphore );
var разрешено : boolean;
begin
ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ;
repeat TS(разрешено, S. взаимоискл) until разрешено;
S.счетчик:=S.счетчик+1;
if S.счетчик < 0 then RELEASE(S); { ДЕБЛОКИРОВАТЬ ПЕРВЫЙ
ПРОЦЕСС ИЗ СПИСКА ПО
S.yкaзaтeль }
S.взаимоискл:=true;
РАЗРЕшИТЬ_ПРЕРЫВАНИЯ;
end;
Обратите внимание, что в данном тексте команда типа «проверка и установка» – TS(разрешено, S.взаимоискл) – работает не с целочисленными, а с булевыми значениями. Практически это ничего не меняет, ибо текст программы и её машинная (двоичная) реализация – это всё-таки разные вещи.