- •Системное программное обеспечение Учебное пособие
- •Введение
- •1.Основные понятия
- •1.1.Функции и ресурсы ос
- •1.2.Структура программного обеспечения
- •1.3.Режимы функционирования компьютера
- •1.4.Классификация ос
- •1.5.Состав ос
- •2.Управление памятью
- •2.1. Основная память
- •2.2.Регистровая память
- •2.3.Кэш память
- •2.4.Организация основной памяти
- •2.4.1.Режимы работы процессоров Intel
- •2.4.2.Преобразование логического адреса в физический в реальном режиме
- •2.4.3.Адресация памяти в защищенном режиме
- •2.5.Управление памятью
- •2.5.1.Модели памяти
- •2.5.2.Динамическое распределение памяти
- •2.5.3.Динамическое распределение памяти в windows nt
- •2.5.4.Функции ос по управлению основной памятью
- •2.6.Виртуальная память
- •2.6.1.Преобразование виртуального адреса в реальный
- •2.6.2.Страничная организация
- •2.6.3.Сегментная организация
- •2.6.4.Странично-сегментная организация
- •2.6.5.Сплошная модель памяти flat
- •2.6.6.Функции для доступа к виртуальной памяти
- •2.6.6.1Освобождение виртуальной памяти
- •2.6.6.2Фиксирование страниц основной памяти
- •2.6.7.Стратегии управления виртуальной памятью
- •2.6.7.1Определение оптимального размера страниц
- •2.6.7.2Поведение программ при подкачке страниц
- •3.Процессы и задачи. Мультипроцессорные системы
- •3.1.Управление процессами
- •3.1.1.Блок управления процессом (pcb)
- •3.1.2.Управление асинхронными параллельными процессами
- •3.2.Мультизадачность
- •3.2.1.Виды мультизадачности:
- •3.2.2.Процессы и задачи
- •3.2.3.Распределение времени между задачами
- •3.2.4.Процессовая мультизадачность
- •3.2.5.Потоковая мультизадачность
- •3.2.6. Синхронизация задач
- •3.2.6.1Ожидание завершения задачи или процесса
- •3.2.6.2Синхронизация с помощью событий
- •3.2.7.Взаимоисключение
- •3.2.7.1Критические секции в программном интерфейсе windows
- •3.2.7.2Блокирующие функции
- •3.2.8.Семафоры
- •3.3.Тупики
- •3.3.1.Условия возникновения тупика
- •3.3.2.Предотвращение тупиков
- •3.3.3. Обход тупиков
- •3.3.4.Обнаружение тупиков
- •3.3.5.Восстановление после тупика
- •3.4.Средства обеспечения мультизадачности в защищенном режиме работы процессора Intel
- •3.4.1.Переключение задач
- •3.5.Обработка прерываний
- •3.5.1.Обработка прерываний в защищенном режиме
- •3.5.2.Обработка аппаратных прерываний
- •3.6.Управление потоками заданий. Планирование заданий и загрузка процессоров
- •3.6.1.Цели планирования
- •3.6.2.Критерии планирования
- •3.6.3.Дисциплины планирования
- •3.6.4.Многоуровневые очереди с обратными связями
- •3.7.Мультипроцессорные архитектуры. Планирование загрузки ресурсов
- •3.7.1.Параллелизм
- •3.7.2.Цели мультипроцессорных систем
- •3.7.3.Автоматическое распараллеливание
- •3.7.3.1Расщепление цикла
- •3.7.3.2Редукция высоты дерева
- •3.7.4.Мультипроцессорные операционные системы
- •3.7.5.Организация мультипроцессорных операционных систем
- •3.7.6.Производительность мультипроцессорных систем
- •3.7.7.Экономическая эффективность мультипроцессорных систем
- •3.7.8.Восстановление после ошибок
- •3.7.9.Перспективы мультипроцессорных систем
- •4.Управление внешней памятью и файловые системы
- •4.1.Структура дискового тома. Таблица разделов
- •4.2.Управление данными
- •4.2.1.Организация данных
- •4.2.2.Методы доступа
- •4.3. Файловые системы
- •4.3.1.Файловая система fat
- •4.3.2.Файловая система fat32
- •4.3.3.Функции windows api для работы с директориями
- •4.3.4.Файловая система windows 95
- •4.3.5.Файловая система нpfs (os/2)
- •4.3.5.1 Структура тома
- •4.3.5.2Файлы и Fnodes
- •4.3.5.3Каталоги
- •4.3.5.4Расширенные атрибуты
- •4.3.5.5Инсталлируемые файловые системы
- •4.3.5.6Проблемы эффективности
- •4.3.5.7Отказоустойчивость
- •4.3.6.Файловая система ntfs (Windows nt)
- •4.3.6.1Главная файловая таблица
- •4.3.6.2Атрибуты файла ntfs
- •4.3.6.3Длинные и короткие имена файлов
- •4.3.6.4Потоки данных
- •4.3.6.5Согласованность с posix
- •4.4.Асинхронные операции с файлами
- •4.5.Файлы, отображаемые на память
- •4.5.1.Создание отображения файла
- •4.5.2.Выполнение отображения на память
- •5.Средства ввода информации
- •5.1.Аппаратные и программные средства ввода информации с клавиатуры
- •5.1.1.Анализ и преобразование скэн-кода
- •5.1.2.Буфер клавиатуры
- •5.1.3.Схема работы буфера
- •5.1.4.Ввод информации с клавиатуры в Windows
- •5.1.4.1Поддержка горячих клавиш (нot-key)
- •5.1.4.2Языки и локализация
- •5.2.Управление манипулятором "мышь"
- •5.2.1.Аппаратные средства манипулятора
- •5.2.2.Программная поддержка "мыши" (на примере ms dos)
- •5.2.3.Основные функции интерфейса программы с манипулятором "мышь" (int 33н)
- •5.2.4.Чтение позиции курсора и состояния кнопок "мыши"
- •5.2.5.Управление мышью в приложениях Windows
- •5.2.5.1Обработка двойного щелчка (Double-Click Messages)
- •5.2.5.2Сообщения неклиентской области
- •5.2.5.3Активизация окна
- •6.Сетевые операционные системы
- •Литература
- •Оглавление
- •Учебное издание
- •394026 Воронеж, Московский просп., 14
3.2.7.1Критические секции в программном интерфейсе windows
Синхронизация задач в рамках одного процесса осуществляется с помощью объекта "критическая секция". Критическая секция создается как структура типа CRITICAL_SECTION в области глобальных переменных. Перед использованием критическая секция должна быть проинициализирована:
VOID InitializeCriticalSection (LPCRITICAL_SECTION lpCritSec);
Удаление критической секции после ее использования:
VOID DeleleCriticalSection (LPCRITICAL_SECTION lpCritSec);
После удаления доступ к критической секции невозможен.
Критическая секция управляет доступом задач к фрагментам кодов с разделенными данными. Критический участок окаймляется функциями входа и выхода из критической секции
VOID EnterCriticalSection (LPCRITICAL_SECTION lpCritSec); VOID LeaveCriticalSection (LPCRITICAL_SECTION lpCritSec);
Для последовательного доступа к ресурсу из задач, созданных разными процессами, используется объект Mutex (Mutually Exclusive - взаимоисключающий). Данный объект, как и событие, может находиться в отмеченном и в неотмеченном состоянии. Когда процесс становится владельцем объекта Mutex, он переводится в неотмеченное состояние, а все остальные процессы, которые обращаются за доступом к этому объекту, должны ожидать, пока он станет отмеченным.
Создание объекта Mutex:
НANDLE CreateMutex (LPSECURITY_ATTRIBUTES lpSecurityAttr,
BOOL bInitialOwner,
LPCTSTR lpName);
Первый параметр передает указатель на структуру с атрибутами системы защиты (NULL - стандартные атрибуты). Второй параметр - флаг начального состояния: True - задача, создавшая Mutex, сразу же захватывает вход в критическую секцию, False - объект создан, но никому не принадлежит. Третий параметр содержит адрес строки с уникальным именем объекта. Другие процессы должны открыть объект Mutex с тем же самым именем:
НANDLE OpenMutex (DWORD fdwAccess,
BOOL bInНerit,
LPCTSTR lpName);
Первый параметр - флаги доступа:
EVENT_ALL_ACCESS - все флаги доступа,
SYNCНRONIZE - разрешить ожидание Mutex
Второй параметр - логический флаг, который разрешает или запрещает наследование идентификаторов.
Третий параметр - указатель на символьную строку, которая содержит имя объекта. Чтобы завладеть Mutex необходимо выполнить функцию WaitForSingleObject (НMutex).
Освобождение объекта выполняется при завершении критической секции с помощью функции:
BOOL ReleaseMutex (НANDLE НMutex);
Полное уничтожение Mutex выполняется закрытием идентификатора функцией CloseНandle.
3.2.7.2Блокирующие функции
Набор этих функций позволяет выполнить операции инкремента, декремента и присваивания для одной глобальной переменной, при этом гарантируется, что выполнение операции не будет прервано по истечении кванта.
long InterLockedIncrement (LPLONG lpAddend);
long InterLockedDecrement (LPLONG lpAddend);
long InterLockedExcНange (LPLONG lpTarget,
long lNewValue);
3.2.8.Семафоры
Механизм взаимоисключения может быть реализован с помощью семафоров: двоичных и считающих. С семафором связаны инициализация и две операции: P(s) - закрытие, V(s) - открытие. Двоичный семафор имеет два состояния - 0 и 1. Закрытый семафор находится в состоянии 0, открытый - в состоянии 1. При инициализации семафора определяется его начальное состояние:
ИнициализацияСемафора(s, 1);
или
ИнициализацияСемафора(s, 0);
Операция P(s):
if s = 1
then s := 0 { закрыть семафор }
else блокировать обратившийся процесс по s;
установить на выполнение готовый процесс;
Операция V(s):
if список процессов, ожидающих s, не пуст
then деблокировать процесс, ожидающий S
else s := 1; { открыть семафор }
Критический участок окаймляется операциями P(s) и V(s). Таким образом, двоичный семафор обеспечивает логику работы с событием (Event).
Считающие семафоры полезны при выделении одиночного ресурса из общего пула. При инициализации в s заносят количественный показатель объема ресурсов пула. P(s) вызывает уменьшение счетчика ресурса на единицу, а V(s)- увеличение счетчика на единицу, т.е.
операция P(s):
if s > 0
then s := s - 1
else ожидать на s;
операция V(s):
if список процессов, ожидающих s не пуст
then разрешить одному процессу работать
else s := s + 1;
Считающие семафоры реализованы в программном интерфейсе Windows. Их использование аналогично использованию событий и критических секций, т.е. семафор может быть в отмеченном или неотмеченном состоянии. Задача ожидает переключения семафора с помощью функции WaitForSingleObject, параметром которой является идентификатор семафора.
Когда семафор становится отмеченным, возобновляется работа задачи. Семафор является объектом, с помощью которого можно синхронизировать задачи, принадлежащие разным процессам: одна задача должна создать семафор, а все остальные - открыть. Функция создания семафора:
НANDLE CreateSemapНore (LPSECURITY_ATTRIBUTES lpSecurityAttr,
long lInitialCount,
long lMaximumCount,
LPCTSTR lpName);
Первым передается указатель на структуру атрибутов системы безопасности. Второй параметр содержит начальное значение счетчика ресурсов. Третий параметр задает максимальное значение счетчика ресурсов. Последним функции передается указатель на символьную строку с уникальным именем семафора.
Открытие семафора:
НANDLE OpenSemapНore (DWORD dwAccess,
BOOL bInНerit,
LPCTSTR lpName);
С помощью первого параметра семафору назначаются флаги доступа
SEMAPНORE_ALL_ACCESS - полный доступ
SEMAPНORE_MODIFY_STATE - разрешение изменения счетчика ресурсов
SYNCНRONIZE - разрешено использование идентификатора в функциях ожидания.
Второй параметр содержит логический флаг разрешения/запрещения наследования идентификатора.
Увеличение счетчика ресурсов (освобождение) выполняется функцией:
BOOL ReleaseSemapНore(НANDLE НSemapНore,
long lReleaseCount,
LPLONG lpPreviouseCount);
Первый параметр - идентификатор семафора; второй параметр - число единиц освобождаемого ресурса; третий параметр - адрес переменной, в которую будет записано предыдущее значение счетчика. Значение lReleaseCount должно быть больше нуля. Если освобождение ресурса состоялось, функция возвращает True. Отметим, что только эта функция позволяет определить количество ресурса семафора.
Уменьшение счетчика (выделение ресурса) выполняется функциями WaitForSingleObject и WaitForMultipleObject.
Задачи, решаемые с помощью семафоров:
1. Взаимоисключение
Два процесса совместно используют общий ресурс. Программный код, на котором реализовано обращение к общему ресурсу, обозначен "критический_участок_1" для первого процесса и "критический_участок_2" для второго. Последовательность входа на критический участок несущественна.
program P1;
var Активный: семафор;
procedure Process1;
begin
while true do
begin ....
P(Активный);
критический_участок_1;
V(Активный); ....
end
end;
procedure Process2;
begin
while true do
begin ....
P(Активный);
критический_участок_2;
V(Активный); ....
end
end;
begin
ИнициализацияСемафора(Активный, 1);
parbegin
Process1;
Process2
parend
end.
2. Синхронизация процессов
Когда процесс выдает запрос на обмен данными с внешним устройством, он блокирует себя в ожидании завершения операции ввода/вывода. Заблокированный процесс должен быть активизирован каким-либо другим процессом. Например, пусть одному процессу необходимо получить уведомление о наступлении некоторого события. Другой процесс может обнаружить, что данное событие произошло.
program P2;
var Событие: семафор;
procedure Process1;
begin ....
P(Событие);
....
end;
procedure Process2; begin
....
V(Событие);
....
end;
begin
ИнициализацияСемафора(Событие, 1);
parbegin
Process1;
Process2
parend
end.
3. "Производитель-потребитель"
Производитель генерирует информацию, потребитель - использует. Пусть они взаимодействуют при помощи одной разделяемой переменной BUFFER, то есть производитель вычисляет некоторое значение и помещает его по адресу переменной, а потребитель после этого считывает значение переменной BUFFER.
program P3;
var Доступ: семафор;
ЧислоЗанесено: семафор;
BUFFER: integer;
procedure Process1; { производитель }
var Результат: integer;
begin
while true do
begin
вычисление Результата;
Р(Доступ);
BUFFER := Результат;
V(Доступ);
V(ЧислоЗанесено)
end
end;
procedure Process2; { потребитель }
var Результат: integer;
begin
while true do
begin
P(ЧислоЗанесено);
P(Доступ);
Результат := BUFFER;
V(Доступ);
вывести Результат
end
end;
begin
ИнициализацияСемафора (Доступ, 1);
ИнициализацияСемафора (ЧислоЗанесено, 0);
parbegin
Process1;
Process2
parend
end.