- •1.Архитектура операционных систем
- •1.1Общие вопросы архитектуры операционных систем
- •1.2Архитектура Windows
- •1.2.1История возникновения Windows
- •1.2.2Архитектура ос Windows
- •1.2.3История возникновения ос Linux
- •1.2.4Архитектура Linux
- •1.2.5Интерфейсы системы unix
- •1.2.6Файловая система unix
- •1.2.7Аутентификация в unix
- •1.2.8Сценарии командной оболочки unix
- •1.3Операционная система qnx
- •1.3.1 Архитектура qnx
- •1.4Выводы
- •1.5Вопросы для самоконтроля
- •2.Типы и алгоритмы работы с оперативной памятью
- •2.1Общие принципы функционирования подсистемы памяти в ос
- •2.1.1Обобщённые принципы управления памятью
- •2.1.2Однозадачная система без подкачки на диск
- •2.1.3Многозадачность с фиксированными разделами
- •2.1.4Подкачка
- •2.1.5Управление памятью с помощью битовых массивов
- •2.1.6Управление памятью с помощью связанных списков
- •2.1.7Виртуальная память
- •2.1.8Многоуровневые таблицы страниц
- •2.1.9Алгоритмы замещения страниц
- •2.2Виртуальная память ос Windows
- •2.2.1Архитектура памяти в ос Windows
- •2.2.2Работа с виртуальной памятью в ос Windows
- •2.2.3Использование виртуальной памяти в приложениях
- •2.3Пример организации страничной памяти на примере linux
- •2.3.1Страничная организация памяти в Linux
- •2.3.2Права доступа к области памяти
- •2.3.3Работа с областями памяти в Linux
- •3.Процессы и потоки
- •3.1Процессы
- •3.1.1Модель процесса
- •3.1.2Создание процесса
- •3.1.3Завершение процесса
- •3.1.4Состояния процессов
- •3.1.5Реализация процессов
- •3.2Потоки
- •3.2.1Реализация потоков
- •3.2.2Реализация потоков на уровне ядра
- •3.2.3Смешанная реализация
- •3.2.4 Метод управления «Активация планировщика»
- •3.2.5Всплывающие потоки
- •3.3Межпроцессное взаимодействие
- •3.3.1Состояние состязания
- •3.3.2Критические секции (Критические области)
- •3.3.3Взаимное исключение с активным ожиданием
- •3.3.4Примитивы межпроцессного взаимодействия
- •3.4Семафоры
- •3.5Мьютексы
- •3.6Организация многопоточной обработки в среде Windows
- •3.6.1Объекты ядра Windows
- •3.6.2Потоки Windows
- •3.6.3Синхронизация потоков в Windows
- •3.6.4Синхронизация потоков с помощью объектов ядра
- •3.6.5Сравнение объектов, используемых для синхронизации потоков
- •3.7Организация процессов и потоков в Linux
- •3.7.1Среда окружения в Linux
- •3.7.2Создание нового процесса. Системный вызов exec.
- •3.7.3Потоки unix. Функции потоков стандарта posix.
- •3.8Синхронизация потоков в unix
- •3.8.1Мьютексы
- •3.8.2Семафоры
- •0,0,0, //Ожидать обнуления семафора
- •0,1,0 // Затем увеличить значение семафора на 1};
- •0,1, 0 // Увеличитьзначение семафора на 1};
2.2.2Работа с виртуальной памятью в ос Windows
Адресное пространство, выделяемое процессу в момент создания, практически все свободно (незарезервировано). Поэтому, чтобы воспользоваться какой-нибудь его частью, нужно выделить в нем определенные регионы через функцию VirtualAlloc (о ней — ниже). Регионом в терминологии ОС Windows называется набор страниц памяти. Операция выделения региона называется резервированием (reserving). При резервировании система обязательно выравнива-ет начало региона с учетом так называемой гранулярности выделения памяти (allocation granularity). Последняя величина в принципе зависит от типа процессора, но для процессоров, x86, 32- и 64-разрядных Alpha и IA-64, — она одинакова и составляет 64 Кб.
Резервируя регион в адресном пространстве, система обеспечивает еще и кратность размера региона размеру страницы. Как и гранулярность выделения ресурсов, размер страницы зависит от типа процессора В частности, для процессоров x86 он равен 4 Кб, а для Alpha (под управлением как 32-разрядной, так и 64-разядной Windows 2000) — 8 Кб. Данная информация зависит от типа процессора, и её нельзя жёстко «зашивать» в программу в виде констант, т.к. это может привести к нарушению доступа. Для определения данных параметров в конкретном окружении Windows используется функция GetSystemInfo:
VOID GetSystemInfo(LPSYSTEM_INFO psinf);
Вы должны передать в GetSystemInfo адрес структуры SYSTEM_INFO, и функция инициализирует элементы этой структуры:
typedef struct _SYSTEM_INFO {
union
{
DWORD dwOemId; // не используйте этот элемент он устарел
struct
{
WORD wProcessorArchitecture;
WORD wRescrved;
};
};
DWORD dwPageSize;
LPVOID lpMinimurnApplirationAddress;
LPVOID lpMaximumApplicationAddress;
DWORD_PTR dwActiveProcessorMask;
DWORD dwNumberOfProcessors;
DWORD dwProcessorType;
DWORD dwAllocationGranularity;
WORD wProcessorLevel;
WORD wProcessorRpvi4inn;
} SYSTEM INFO *LPSYSlEM_INFO;
При загрузке система определяет значения элементов этой структуры, для конкретной системы их значения постоянны Функция GetSystemInfo предусмотрена специально для того, чтобы и приложения могли получать эту информацию. Из всех элементов структуры лишь четыре имеют отношение к памяти. Они описаны в таблице 2.2.
Таблица 2.2. Параметры выделения памяти GetSystemInfo
Элемент |
Описание |
dwPageStze |
Размер страницы памяти. На процессорах x86 это значение равно 4096, а на процессорах Alpha — 8192 байтам. |
IpMinimumApplicationAddress |
Минимальный адрес памяти доступного адресного пространен для каждого процесса. В Windows 98 это значение равно 4 194 304, или 0x00400000, поскольку нижние 4 Мб адресного пространства каждого процесса недоступны. В Windows 2000 это значение равно 65 536, или 0x00010000, так как в этой сиcтеме резервируются лишь первые 64 Кб адресного пространства каждого процесса. |
lpMaximwnApplicationAddress |
Максимальный адрес памяти доступного адресного пространства, отведенного в "личное пользование" каждому процессу. В Windows 98 этот адрес равен 2 147 483 647, или 0x7FFFFFFF, так как верхние 2 Гб занимают общие файлы, проецируемые в память, и разделяемый код операционной системы. В Windows 2000 этот адрес соответствует началу раздела для кода и данных режима ядра за вычетом 64 Кб. |
dwAllocationGranularity |
Гранулярность резервирования регионов адресного пространства. Это значение составляет обычно 64Кб для всех платформ Windows. |
В некоторых случаях система сама резервирует некоторые регионы адресного пространства в интересах Вашего процесса, например, для хранения блока переменных окружения процесса (process environment block, PEB). Этот блок — небольшая структура данных, создаваемая, контролируемая и разрушаемая исключительно операционной системой. Выделение региона под РЕВ-блок осуществляется в момент создания процесса.
Кроме того, для управления потоками, существующими на данный момент в процессе, система создает блоки переменных окружения потоков (thread environment blocks, TEBs). Регионы под эти блоки резервируются и освобождаются по мере начала и завершения потоков в процессе.
Требуя от разработчика резервировать регионы с учетом гранулярности выделения памяти (а эта гранулярность на сегодняшний день составляет 64 Кб), сама система этих правил не придерживается Поэтому вполне вероятно, что границы региона, зарезервированного под РЕВ- и ТЕВ-блоки, не будут кратны 64 Кб. Тем не менее, размер такого региона обязательно кратен размеру страниц, характерному для данного типа процессора.
Если попытаться зарезервировать регион размером 10 Кб, система автоматически округлит заданное Вами значение до большей кратной величины. А это значит что на x86 будет выделен регион размером 12 Кб, а на Alpha — 16 Кб.
Когда зарезервированный регион адресного пространства становится не нужен, его следует вернуть в общие ресурсы системы. Эта операция — освобождение (releasing) региона — осуществляется вызовом функции VirtualFree
Чтобы зарезервированный регион адресного пространства можно было использовать, необходимо выделить физическую память и спроецировать её на этот регион. Такая операция называется передачей физической памяти (committing physical storage). Чтобы передать физическую память зарезервированному региону, Вы обращаетесь все к той же функции VirtualAlloc.
Передавая физическую память регионам, нет нужды отводить ее целому региону. Можно, скажем, зарезервировать регион размером 64 Кб и передать физическую память только его второй и четвертой страницам.
Когда физическая память, переданная зарезервированному региону, больше не нужна, ее освобождают. Эта операция — возврат физической памяти (decommitting physical storage) — выполняется вызовом функции VirtualFree.
Отдельным страницам физической памяти можно присвоить свои атрибуты за-щиты показанные в табл. 2.2
Таблица 2.2. Атрибуты защиты
Атрибут защиты |
Описание |
PAGE_NOACCESS |
Попытки чтения, записи или исполнения содержимого памяти на этой странице вызывают нарушение доступа |
PAGE_READONLY |
Попытки записи или исполнения содержимого памяти на этой странице вызывают нарушение доступа |
PAGE_READWRITE |
Попытки исполнения содержимого памяти на этой странице вызывают нарушение доступа |
PAGE_EXECUTE |
Попытки чтения или записи на этой странице вызывают нарушение доступа |
PAGE_EXECUTE_READ |
Попытки записи на этой странице вызывают нарушение доступа |
PAGE_EXECUTE_READWRITE |
На этой странице возможны любые операции |
PAGE_WRITECOPY |
Попытки исполнения содержимого памяти на этой странице выбывают нарушение доступа, попытка записи приводит к тому, что процессу предоставляется копия данной страницы |
PAGE_EXECUTE_WRITECOPY |
На этой странице возможны любые операции, попытка записи приводит к тому, что процессу предоставляется копия данной страницы |
На процессорных платформах x86 и Alpha атрибут PAGE_EXECUTE не поддерживается, хотя в операционных системах такая поддержка предусмотрена. Перечисленные процессоры воспринимают запрос на чтение как запрос на исполнение. Поэтому присвоение памяти атрибута PAGE_EXECUTE приводит к тому, что на этих процессорах она считается доступной и для чтения, Но полагаться на эту особенность не стоит, поскольку в реализациях Windows на других процессорах все может встать на свои места. В Windows 98 страницам физической памяти можно присвоить только три атрибута защиты: PAGE_NOACCESS, PAGE_READONLY и PAGE_READWRITE.
Атрибуты защиты, перечисленные в предыдущей таблице, достаточно понятны, кроме двух последних: PAGE_WRITECOPY и PAGE_EXECUTE_WRITECOPY. Они предназначены специально для экономного расходования оперативной памяти и места в страничном файле. Windows поддерживает механизм, позволяющий двум и более процессам разделять один и тот же блок памяти. Например, если Вы запустите 10 экземпляров программы Notepad, все экземпляры будут совместно использовать одни и те же страницы с кодом и данными этой программы. Проблем не возникает, пока процессы ничего не записывают в общие блоки памяти.
Чтобы предотвратить ошибки, которые неизбежно возникнут при записи в указанные страницы, операционная система присваивает общему блоку памяти атрибут защиты "копирование при записи" (copy-on-write). Когда поток в одном процессе попытается что-нибудь записать в общий блок памяти, в дело тут же вступит система и проделает следующие операции:
1. Найдет свободную страницу в оперативной памяти. Заметьте, что при первом проецировании модуля на адресное пространство процесса эта страница будет скопирована на одну из страниц, выделенных в страничном файле. Поскольку система выделяет нужное пространство в страничном файле еще при первом проецировании модуля, сбои на этом этапе маловероятны.
2. Скопирует страницу с данными, которые поток пытается записать в общий блок памяти, на свободную страницу оперативной памяти, полученную на этапе 1. Последней присваивается атрибут защиты PAGE_WRITECOPY или PAGE_EXECUTE_WRITECOPY. Атрибут защиты и содержимое исходной страницы не меняются.
3. Отобразит виртуальный адрес этой страницы в процессе на новую страницу в оперативной памяти.
Когда система выполнит эти операции, процесс получит свою копию нужной страницы памяти.
Кроме того, при резервировании адресного пространства или передаче физической памяти через VirtualAlloc нельзя указывать атрибуты PAGE_WRITECOPY или PAGE_EXECUTE_WRITECOPY. Иначе вызов VirtualAlloc даст ошибку, a GetLastError вернет код ERROR_INVALID_PARAMETER. Дело в том, что эти два атрибута используются операционной системой, только когда она проецирует образы EXE- или DLL-файлов. Windows 98 не поддерживает "копирование при записи" Обнаружив запрос на применение такой защиты, Windows 98 тут же делает копии данных, не дожидаясь попытки записи в память.
Кроме рассмотренных атрибутов защиты, существует три флага атрибутов защиты PAGE_NOCACHE, PAGE_WRITECOMBINE и PAGE_GUARD. Они комбинируются с любыми атрибутами защиты (кроме PAGE_NOACCESS) побитовой операцией OR.
Флаг PAGE_NOCACHE отключает кэширование переданных страниц. Как правило, использовать этот флаг не рекомендуется; он предусмотрен главным образом для разработчиков драйверов устройств, которым нужно манипулировать буферами памяти.
Флаг PAGE_WRITECOMBINE тоже предназначен для разработчиков драйверов ycтройств. Он позволяет объединять несколько операций записи на устройство в один пакет, что увеличивает скорость передачи данных
Флаг PAGE_GUARD позволяет приложениям получать уведомление (через механизм исключений) в тот момент, когда на страницу записывается какой-нибудь байт. Windows 2000/XP использует этот флаг при создании стека потока.
Windows 98 игнорирует флаги атрибутов защиты PAGE_NOCACHE, PAGE_WRITECOMBINE и PAGE_GUARD
