
- •Введение
- •1. Лабораторная работа № 1
- •1.1. Цель работы
- •1.2. Теоретическое введение
- •1.2.1. Получение информации об операционной системе
- •1.2.2. Получение информации из реестра
- •1.2.3. Получение информации о системных каталогах Windows
- •1.2.4. Получение информации о диске
- •1.3. Создание приложения для получения характеристик компьютера и операционной системы
- •Контрольные вопросы
- •2. Лабораторная работа №2
- •2.1.Цель работы
- •2.2. Теоретическое введение
- •2.2.1. Процедуры и функции для работы с виртуальной памятью
- •2.3. Создание приложения, работающего с виртуальной памятью
- •2.4. Задание для самостоятельной работы
- •Контрольные вопросы
- •3. Лабораторная работа № 3
- •3.1. Цель работы
- •3.2. Пример использования механизма выделения виртуальной памяти для решения конкретных задач
- •3.3. Задания для самостоятельной работы
- •Контрольные вопросы
- •4. Лабораторная работа № 4
- •4.1. Цель работы
- •4. 2. Теоретическое введение
- •4.2.1 Создание или открытие объекта ядра «файла»
- •4.2.2 Создание объекта ядра «файл, проецируемый в память»
- •4.2.3 Проецирование файловых данных на адресное пространство процесса
- •4.2.4 Отмена проецирования на адресное пространство процесса объекта ядра «файл, проецируемый в память»
- •4.2.5 Закрытие объектов ядра «файл, проецируемый в память» и «файл»
- •4.3 Примеры программ, выполняющих проецирование в память
- •4.3.1 Пример 1
- •4.3.2 Пример 2
- •4.4. Задания для самостоятельной работы
- •Контрольные вопросы
- •5. Лабораторная работа № 5
- •5.1.Цель работы
- •5.2. Теоретическое введение
- •5.2.1. Создание процесса
- •5.2.2. Запуск внешней программы функцией WinExec
- •5.2.3. Запуск внешней программы и открытие документа функцией ShellExecute
- •При успешном выполнении функция ShellExecute возвращает целое значение, большее 32. Значение меньшее или равное 32 указывает на ошибку. Значения эти те же, что и для функции WinExec.
- •5.2.4. Создание потока
- •5.2.5. Завершение процесса
- •5.2.6. Завершение потока
- •5.2.7. Изменение класса приоритета процесса
- •5.2.8. Получение информации о классе приоритета процесса
- •5.2.9. Изменение уровня приоритета потока
- •5.2.10. Получение информации о приоритете потока
- •5.3. Примеры программ для работы с процессами и потоками
- •5.3.1. Создание процесса с помощью функции CreateProcess.
- •5.3.2. Создание процесса с помощью функции WinExec.
- •5.3.3. Создание процесса с помощью функции ShellExecute.
- •5.3.4. Создание многопоточного приложения.
- •5.4. Задания для самостоятельной работы
- •Контрольные вопросы
- •6. Лабораторная работа № 6
- •6.1. Цель работы
- •6.2. Теоретическое введение
- •6.2.1. Получение «мгновенного снимка» системы
- •6.2.2. Получение информации о процессах
- •6.2.3. Получение информации о потоках
- •6.2.4. Получение информации о модулях
- •6.2.5. Информация о кучах (heap)
- •6.2.6. Информация о виртуальной памяти.
- •6.2.7. Алгоритм работы функций ToolHelp
- •6.2.8. Как получить карту памяти любого процесса
- •6.3. Пример использования функций ToolHelp
- •6.4. Задания для самостоятельной работы
- •Контрольные вопросы
- •7. Лабораторная работа № 7
- •7.1. Цель работы
- •7.2. Теоретическое введение
- •7.2.1. Критические секции
- •7.2.2. Синхронизация с использованием объектов ядра
- •7.2.3. Wait-функции
- •7.2.4. Синхронизация с использованием процессов и потоков
- •7.2.5. Объекты Mutex
- •7.2.6. Семафоры
- •7.2.7. События
- •7.3 Примеры работы с объектами синхронизации
- •7.3.1 Пример 1
- •7.3.1 Пример 2
- •7.4. Задания для самостоятельной работы
- •Контрольные вопросы
- •8. Лабораторная работа № 8
- •8.1. Цель работы
- •8.2 Теоретическое введение
- •8.2.1 Создание dll
- •8.2.2 Неявная загрузка dll
- •8.2.3 Явная загрузка dll
- •8.2.4 Внедрение dll в адресное пространство другого процесса
- •8.3 Пример работы с dll
- •8.3.1 Создание dll, которая выполняет перехват нажатых клавиш
- •8.3.2 Разработка приложения, которое выполняет анализ и обработку нажатых клавиш.
- •8.4 Индивидуальные задания
- •Контрольные вопросы
- •9.2.2. Функции для работы с объектом «уведомление об изменении файловой системы»
- •9.3. Пример работы системы уведомления об изменениях в файловой системе
- •9.4. Задания для самостоятельной работы
- •Контрольные вопросы
- •Литература
- •214013 Г. Смоленск, Энергетический проезд, 1
7.2.6. Семафоры
Объекты ядра «семафор» используются для учета ресурсов Как и все объекты ядра, они содержат счетчик числа пользователей, но, кроме того, поддерживают два 32 битных значения со знаком: одно определяет максимальное число ресурсов (контролируемое семафором), другое используется как счетчик текущего числа ресурсов
Для семафоров определены следующие правила:
когда счетчик текущего числа ресурсов становится больше 0, семафор переходит в свободное состояние,
если этот счетчик равен 0, семафор занят,
система не допускает присвоения отрицательных значений счетчику текущего числа ресурсов;
счетчик текущего числа ресурсов не может быть больше максимального числа ресурсов
Не следует путать счетчик текущего числа ресурсов со счетчиком числа пользователей объекта-семафора
Объект ядра «семафор» создается вызовом функции CreateSemapbore: function CreateSemaphore(lpSemaphoreAttributes: PSecurityAttributes;
lInitialCount, lMaximumCount: Longint; lpName: PChar): THandle;
где lpSemaphoreAttributes - указывает на структуру SECURITY_ATTRIBUTES, которая содержит информацию о защите объекта ядра «семафор». Если защиты не нужно в этот параметр заносится nil.
lInitialCount – счетчик текущего числа ресурсов.
lMaximumCount – максимальное число ресурсов, контролируемое семафором. Данный параметр должен быть больше 0.
lpName – указатель на строку, заканчивающуюся двоичным нулем и содержащую имя объекта «семафор». Применяется в тех случаях, когда объект «семафор» используется для синхронизации потоков разных процессов. Если объект «семафор» используется для синхронизации потоков одного процесса, этот параметр устанавливается в nil.
При успешном выполнении функции CreateSemaphore возвращает дескриптор семафора, В случае ошибки функция возвращает nil. Причем, если при вызове функции CreateSemaphore указывается имя семафора и объект «семафор» с таким именем уже существует, то функция вернет значение – nil, а функция GetLastError вернет значение - ERROR_ALREADY_EXISTS.
Любой процесс может получить свой («процессно-зависимый») дескриптор существующего объекта «семафор», вызвав функцию OpenSemaphore:
function OpenSemaphore(dwDesiredAccess: DWORD; bInheritHandle: Boolean;
lpName: PChar): THandle;
где dwDesiredAccess - определяет требуемый доступ к объекту «семафор». Возможные значения данного параметра приведены в таблице 7.2.
bInheritHandle - определяет тип наследования данного дескриптора. Если данный параметр имеет значение TRUE, процесс, создаваемый функцией CreateProcess, будет наследовать данный дескриптор. Если же данный параметр имеет значение FALSE, дескриптор семафора не будет наследуемым.
lpName - указатель на сроку, заканчивающуюся двоичным нулем и содержащую имя объекта «семафор».
Таблица 7.2 Значения параметра dwDesiredAccess
Значение |
Описание |
SEMAPHORE_ALL_ACCESS |
Означает все возможные флаги доступа для объекта «семафор» |
SEMAPHORE _MODIFY_STATE |
Объект «семафор» можно использовать только в функции ReleaseSemaphore для изменения счетчика текущего числа ресурсов |
SYNCHRONIZE |
Допускается использование дескриптора объекта «семафор» в любой wait- функции для ожидания освобождения семафора. |
Поток получает доступ к ресурсу, вызывая одну из Wait-функций и передавая ей дескриптор семафора. Wait-функция проверяет у семафора счетчик текущего числа ресурсов, если его значение больше 0 (семафор свободен), уменьшает значение этого счетчика на 1, и вызывающий поток остается планируемым
Если Wait-функция определяет, что счетчик текущего числа ресурсов равен 0 (семафор занят), система переводит вызывающий поток в состояние ожидания. Когда другой поток увеличит значение этого счетчика, система вспомнит о ждущем потоке и снова начнет выделять ему процессорное время (а он, захватив ресурс, уменьшит значение счетчика на 1).
Поток увеличивает значение счетчика текущего числа ресурсов, вызывая функцию ReleaseSemaphore:
function ReleaseSemaphore(hSemaphore: THandle; lReleaseCount:
Longint; lpPreviousCount: Pointer): Boolean;
Где hSemaphore – дескриптор семафора.
Данная функция складывает величину lReleaseCount со значением счетчика текущего числа ресурсов. Обычно в параметре lReleaseCount передают 1, но это вовсе не обязательно. Функция возвращает исходное значение счетчика ресурсов в lpPreviousCount. Если исходное значение счетчика в приложении не используется, то вместо параметра lpPreviousCount записывается значение nil.
При успешном выполнении функция ReleaseSemaphore возвращает значение TRUE.