- •Лихачёв д.С.
- •1 Понятие операционной системы. Классификация операционных систем
- •2 Сетевые операционные системы
- •3 Назначение и основные функции операционных систем. Требования к современным операционным системам.
- •4 Назначение и основные функции операционных систем. Функции операционных систем по управлению ресурсами компьютера.
- •5 Функции операционных систем по управлению ресурсами компьютера. Управление процессами.
- •6 Функции операционных систем по управлению ресурсами компьютера. Управление памятью.
- •7 Функции операционных систем по управлению ресурсами компьютера. Управление файлами и внешними устройствами. Поддержка пользовательского интерфейса.
- •8 Функции операционных систем по управлению ресурсами компьютера. Защита данных и поддержка администрирования. Поддержка интерфейса прикладного программирования.
- •9 Обобщённая структура операционной системы.
- •10 Архитектура операционных систем на основе монолитного ядра.
- •11 Особенности работы ядра в привилегированном режиме.
- •12 Многослойная структура операционной системы.
- •13 Микроядерная архитектура.
- •14 Подсистема операционной системы управления памятью. Понятие виртуальной памяти.
- •15 Методы распределения памяти. Распределение памяти фиксированными разделами.
- •16 Методы распределения памяти. Распределение памяти динамическими разделами.
- •17 Методы распределения памяти. Распределение памяти перемещаемыми разделами.
- •18 Методы распределения памяти. Страничное распределение.
- •19 Методы распределения памяти. Сегментное распределение.
- •20 Методы распределения памяти. Странично-сегментное распределение. Свопинг.
- •21 Многозадачность. Особенности реализации многозадачности в системах пакетной обработки.
- •22 Многозадачность. Особенности реализации многозадачности в системах разделения времени.
- •23 Понятие процесса. Подсистема операционной системы управления процессами. Состояния процесса. Контекст и дескриптор процесса.
- •24 Совместное использование объектов ядра несколькими процессами. Наследование описателя объекта.
- •25 Совместное использование объектов ядра несколькими процессами. Именованные объекты
- •26 Совместное использование объектов ядра несколькими процессами. Дублирование описателей объектов
- •27Планирование и диспетчеризация потоков.
- •28 Вытесняющие и невытесняющие алгоритмы планирования.
- •29 Алгоритмы планирования, основанные на приоритетах.
- •30 Алгоритмы планирования, основанные на квантовании.
- •31 Принципы работы с потоками вWindows. Распределение процессорного времени между потоками
- •32 Приостановка и возобновление потоков/процессов
- •33 Потоки вWindows. Приоритеты потоков и процессов
- •34 Задача синхронизации потоков
- •35 Синхронизация потоков с объектами ядра. Функции ожидания объектов ядра
- •36 Мьютексы. Создание, открытие, освобождение и удаление мьютекса. Отказ от мьютекса
- •37 Семафоры. Создание, открытие, освобождение и удаление семафора
- •38 Понятие сетевой операционной системы. Компьютерная сеть
- •39 Типичная структура сетевых операционных систем.
- •40 Сетевые службы и сетевые ресурсы
- •41 Архитектура взаимодействия типа клиент – сервер.
- •42 Многоуровневая структура коммуникаций. Эталонная модель взаимодействия открытых систем osi. Принцип пакетной передачи данных.
- •43 Технологии, используемые для построения компьютерных сетей.
- •44 Стек протоколов tcp/ip. Ip-адресация.
- •45 Понятие программной модели ia-32. Регистры общего назначения. Сегментные регистры.
- •46 Понятие программной модели ia-32. Регистры состояния и управления.
- •47 Режимы работы микропроцессора
- •48 Понятие оперативной памяти. Формирование адреса в процессорах с архитектурой ia-32.
- •49 Режимы адресации для процессоров с архитектурой ia-32. Работа с массивами на ассемблере.
- •50 Понятие модульного программирования. Понятие подпрограммы. Ассемблерные процедуры и функции.
- •51 Способы передачи аргументов в процедуру.
- •52 Программная модель математического сопроцессора.
- •2. Три служебных регистра:
24 Совместное использование объектов ядра несколькими процессами. Наследование описателя объекта.
Иногда возникает необходимость в разделении объектов ядра между потоками, исполняемыми в разных процессах, например:
объекты “проекции файлов”, которые позволяют двум процессам, исполняемым на одной машине, совместно использовать одни и те же блоки данных;
почтовые ящики (mailslots) и именованные каналы (namedpipes), которые дают возможность программам обмениваться данными с процессами, исполняемыми на других машинах в сети;
мьютексы (mutexes), семафоры (semaphores) и события (events), которые позволяют синхронизировать потоки, исполняемые в разных процессах, чтобы одно приложение могло уведомить другое об окончании той или иной операции.
Однако поскольку описатели объектов ядра имеют смысл только в конкретном процессе, разделение объектов ядра между несколькими процессами в Win32 весьма трудоёмкая задача. Главная причина сделать описатели “процессо-зависимыми” – устойчивость операционной системы к сбоям. Если бы описатели объектов ядра были общесистемными, то один процесс мог бы получить описатель объекта, используемого другим процессом, и устроить в этом процессе настоящий хаос. Другая причина – защита. Объекты ядра защищены, и процесс, прежде чем оперировать с ними, должен запрашивать разрешение на доступ к ним. Процесс – создатель объекта может предотвратить несанкционированный доступ к этому объекту со стороны другого процесса.
Могут использоваться следующие механизмы, позволяющие процессам совместно использовать одни и те же объекты ядра:
наследование описателя объекта;
именованные объекты;
дублирование описателей объектов.
Наследование применимо, только когда процессы связаны “родственными” отношениями (родительский – дочерний). Например, родительскому процессу доступны один или несколько описателей объектов ядра, и он решает, породив дочерний процесс, передать ему по наследству доступ к своим объектам ядра. Чтобы такой сценарий наследования сработал, родительский процесс должен выполнить несколько операций.
Во-первых, еще при создании объекта ядра сообщить системе, что ему нужен наследуемый описатель этого объекта. Cледует иметь в виду, чтоописателиобъектов ядра наследуются, носами объекты ядра – нет.
Следующий этап – родительский процесс порождает дочерний.
Объект типа процесс (process) может быть использован для того, чтобы приостановить выполнение потока в том случае, если он для своего продолжения нуждается в завершении процесса. С практической точки зрения проблема порождения дочернего процесса встает, когда нужно в рамках вашего приложения исполнить приложение, созданное кем-то другим, или, к примеру, запустить сеансMS-DOS.
25 Совместное использование объектов ядра несколькими процессами. Именованные объекты
Ещё один способ, позволяющий нескольким процессам совместно использовать одни и те же объекты ядра, связан с именованием этих объектов. Именование допускают многие объекты ядра. Следующие функции создают именованные объекты ядра:
HANDLE CreateMutex(
PSLCURITY_ATTRIBUTES psa,
BOOL bInitialOwner,
PCTSTR pszName);
HANDLE CreateEvent(
PSECURITY_ATTRIBUTES psa,
BOOL bManualReset,
BOOL bInitialState,
PCTSTR pszName);
HANDLE CreateSemaphore(
PSECURITY_ATTRIBUTES psa,
LONG lInitialCount,
LONG lMaximumCount,
PCTSTR pszNarne);
HANDLE CreateWaitableTimer(
PSLCURITY_ATTRIBUTES psa,
BOOL bManualReset,
PCTSTR pszName);
HANDLE CreateFileMapping(
HANDLE hFile,
PSECURITY_ATTRIBUTES psa,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
PCTSTR pszName);
HANDLE CreateJobObject(
PSECURITY_ATTRIBUTES psa,
PCTSTRpszName);
Последний параметр, pszName, у всех этих функций одинаков. Передавая в нем NULL можно создать безымянный (анонимный) объект ядра. В этом случае можно разделить объект между процессами. Чтобы разделять объект по имени, необходимо присвоить ему какое-нибудь имя. Тогда вместо NULL в параметреpszNameнужно передать адрес строки с именем, завершаемой нулевым символом. Имя может быть длиной до MAX_PATH знаков (это значение определено как 260). К сожалению, Microsoft ничего не сообщает о правилах именования объектов ядра. Например, создавая объект с именемJeffObj, нет гарантии того, что в системе еще нет объекта ядра с таким именем. И что хуже, все эти объекты делят единое пространство имен. Из-за этого следующий вызовCreateSemaphoreбудет всегда возвращать NULL:
HANDLE hMutex = CreateMutex(NULL. FALSE, "JeffObj");
HANDLE hSem = CreateSemaphore(NULL, 1, 1, "JeffObj");
DWORD dwErrorCode = GetLastError();
После выполнения этого фрагмента значение dwErrorCode будет равно ERROR_INVALID_HANDLE.
Рассмотрим, как разделять их между процессами по именам. Допустим, после запуска процесса А вызывается функция:
HANDLE hMutexPronessA = CreateMutex( NULL,
FALSE,
"JeffMutex");
Этот вызов заставляет систему создать новый объект ядра "мъютекс" и присвоить ему имя JeffMutex. ОписательhMutexProcessAв процессе А не является наследуемым, — он и не должен быть таковым при простом именовании объектов.
Спустя какое-то время некий процесс порождает процесс В. Необязательно, чтобы последний был дочерним от процессаА; он может быть порожден Explorer или любым другим приложением. Когда процесс В приступает к работе, исполняется код:
HANDLE hMutexProcessB = CreateMutex( NULL,
FALSE,
"JeffMutex");
При этом вызове система сначала проверяет, не существует ли уже объект ядра с таким именем. Если да, то ядро проверяет тип этого объекта. Поскольку есть попытка создать мьютекс и его имя тоже JeffMutex, система проверяет права доступа вызывающего процесса к этому объекту. Если у него есть все права, в таблице описателей, принадлежащей процессуВ, создается новая запись, указывающая на существующий объект ядра. Если же вызывающий процесс не имеет полных прав на доступ к объекту или если типы двух объектов с одинаковыми именами не совпадают, вызовCreateMutexзаканчивается неудачно и возвращается NULL.
Однако, хотя процесс Вуспешно вызвалCreateMutex, новый объект-мьютекс он не создал. Вместо этого он получил свой описатель существующего объекта-мьютекса. Счетчик объекта, конечно же, увеличился на 1, и теперь этот объект не разрушится, пока его описатели не закроют оба процесса —АиВ. Значения описателей объекта в обоих процессах скорее всего разные, но так и должно быть, каждый процесс будет оперировать с данным объектом ядра, используя свой описатель.
Вызывая CreateMutex, процессВпередает ей атрибуты защиты и второй параметр. Эти параметры игнорируются, если объект с указанным именем уже существует. Приложение может определить, что оно делает: создает новый объект ядра или просто открывает уже существующий, — вызвавGetLastErrorсразу же после вызова одной из Create-функций:
HANDLE hMutex = CreateMutex(&sa, FALSE, "JeffObj");
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// открыт описатель существующего объекта sa.lpSecurityDescriptor и второй параметр (FALSE) игнорируются
}
else
{
// создан совершенно новый объект sa.lpSecurityDescriptor и второй параметр (FALSE) используются при создании объекта
}
Есть и другой способ разделения объектов по именам. Вместо вызова Create-функции процесс может обратиться к одной из следующих Open-функций:
HANDLE OpenMutex(
DWORD dwDESIredAccess,
BOOL bInheritHandle,
PCTSTR pszName);
HANDLE OpenEvent(
DWORD dwDESIredAccess,
BOOL bInheritHandle,
PCTSTR pszName);
HANDLE OpenSemaphore(
DWORD dwDESIredAccess,
BOOL bInheritHandle,
PCTSTR pszName);
HANDLE OpenWaitableTimer(
DWORD dwDESIredAccess,
BOOL bInheritHandle,
PCTSTR pszName);
HANDLE OpenFileMapping(
DWORD dwDESIredAccess,
BOOL bInheritHandle,
PCTSTR pszName);
HANDLE OpenJobObject(
DWORD dwDESIredAccess,
BOOL bInheritHandle,
PCTSTR pszName);
Все эти функции имеют один прототип. Последний параметр, pszName, определяет имя объекта ядра. В нем нельзя передать NULL — только адрес строки с нулевым символом в конце. Эти функции просматривают единое пространство имен объектов ядра, пытаясь найти совпадение. Если объекта ядра с указанным именем нет, функции возвращают NULL, aGetLastError— код 2 (ERROR_FILE_NOT_FOUND). Но если объект ядра с заданным именем существует и если его тип идентичен тому, что указан, система проверяет, разрешен ли к данному объекту доступ запрошенного вида (через параметрdwDesiredAccess). Если такой вид доступа разрешен, таблица описателей в вызывающем процессе обновляется, и счетчик числа пользователей объекта возрастает на 1. Если параметруbInheritHandleприсвоено значение TRUE, то получится наследуемый описатель.
Главное отличие между вызовом Create- и Open-функций в том, что при отсутствии указанного объекта Create-функция создает его, а Open-функция просто уведомляет об ошибке.