- •Введение
- •1. Методы и средства получения информации о ресурсах вычислительной системы
- •1.1. Получение информации о выполняющихся процессах и используемых ими ресурсах
- •1.1.1. Получение списка процессов, выполняющихся в системе
- •1.1.1.1. Использование функций CreateToolHelp32Snapshot () и Process32xxxx() для получения списка имен процессов
- •1.1.1.2. Использование функций CreateToolHelp32Snapshot () и Thread32xxxx() для получения сведений о приоритетах потоков процессов
- •1.1.2. Использование функций CreateToolHelp32Snapshot () и Module32xxxx() для получения списка модулей
- •1.1.3. Использование функций CreateToolHelp32Snapshot () и Heap32Listxxxx() для получения списка куч
- •1.1.4. Получение дополнительной информации о процессах и потоках
- •1.1.4.2. Получение информации счетчиков ввода-вывода и количества описателей (дескрипторов)
- •Получение информации о загруженных драйверах
- •1.1.6. Использование функции NtQuerySystemInformation
- •1.1.6.1. Назначение аргументов функции
- •1.1.6.2. Вызов функции NtQuerySystemInformation
- •1.1.6.3. Получение сведений о процессах и потоках
- •1.1.6.4. Преобразование данных из формата FileTime в формат SystemTime
- •1.1.6.5. Вычисление загрузки процессора
- •1.1.7 Формирование протокола использования процессора
- •1.2. Получение информации о ресурсах виртуальной памяти и системе
- •1.2.1. Функции и структуры данных управления виртуальной памятью
- •1.2.2. Получение информации о структуре виртуального адресного пространства
- •1.3. Получение информации о файловой системе
- •1.3.1. Определение имеющихся логических дисков
- •1.3.2. Получение информации о томах
- •1.3.3. Поиск файлов
- •1.4. Методы и средства работы с реестром
- •1.4.1. Открытие и закрытие родительского раздела
- •1.4.2. Создание подразделов
- •1.4.3. Установка значения параметра
- •1.4.4. Получение значения параметра
- •1.4.5. Уведомление приложения об изменениях в разделе реестра
- •1.4.6. Использование компонента Registry
- •1.4.7. Поиск в разделе реестра имен файлов приложений, являющихся локальными серверами автоматизации
- •1.5. Использование функции ReadDirectoryChangesW для отслеживания изменений в файловой системе
- •2. Средства управления выполнением прикладных процессов
- •2.1. Функции Win32 для создания и управления процессами
- •2.2. Функции Win32 для создания и управления потоками
- •2.3. Завершение выбранного процесса
- •3. Методы реализации мониторинга ресурсов
- •3.1. Мониторинг процессов
- •3.2. Программирование «с защитой от ошибок»
- •Требования к разрабатываемому монитору
- •4.1. Требования к выполняемым функциям
- •4.2. Требования к реализации
- •4.3. Требования к документации
- •4.4. Список вопросов для приема курсовой работы
- •Библиографический список
- •Приложение 1 График выполнения курсовой работы
- •Приложение 2 Примеры описания реализации отдельных функций монитора и оформления разделов пояснительной записки
- •1. Вывод списка выполняющихся процессов в виде дерева.
- •2. Формирование протокола использования процессора
- •3. Протоколирование моментов времени внесения изменений в файловую систему с записью выполненных изменений и имён приложений, выполнивших изменения.
- •4. Поиск одинаковых файлов, хранящихся в различных каталогах (необходимо обеспечить возможно большую скорость выполнения операции). Вводить имена файлов или каталогов перед началом поиска не следует.
- •9. Вывод списка прав текущего пользователя
- •10. Пример составления перечня используемых компонентов
- •11. Пример заполнения таблицы использованных компонентов
- •12. Пример описания основных переменных
- •13. Пример составления руководства пользователя по инсталляции и использованию монитора
- •14. Пример описания процедуры тестирования монитора
- •Системное программное обеспечение Учебное пособие
- •443100, Г. Самара, ул. Молодогвардейская, 244.
- •443100, Г. Самара, ул. Молодогвардейская, 244. Корпус № 8
Получение информации о загруженных драйверах
Для получения информации о загруженных в память драйверах и их адресах используются функции EnumDeviceDrivers(), GetDeviceDriverBaseNameA(), GetDeviceDriverFileNameA(), вызываемые из библиотеки Psapi.dll. Прототипы функций имеют следующий вид:
function EnumDeviceDrivers(lp : pointer; cb : DWORD ;
lpcbNeeded : lpDWORD ): BOOL; stdcall external 'psapi.dll';
function GetDeviceDriverBaseNameA(lp : pointer; lpBaseName : lpstr; nSize : DWORD): BOOL; stdcall external 'psapi.dll';
function GetDeviceDriverFileNameA( lp : pointer;
lpFilename : LPTSTR; nSize :DWORD): DWORD ; stdcall external 'psapi.dll';
Функция EnumDeviceDrivers ( lp : pointer; cb : DWORD ; lpcbNeeded : lpDWORD ): BOOL; возвращает массив указателей на загруженные в ОП драйверы. Указатель на массив задается первым аргументом функции, второй аргумент (входной параметр) задает размер массива, если этот размер является недостаточным, требуемый размер возвращается функцией в третьем параметре. Пример вызова функции
var
pdriver : array [1..138] of cardinal;
lpcbNeeded : dword;
if EnumDeviceDrivers( @pdriver, sizeof(pdriver), @lpcbNeeded )
then label1.Caption := inttostr(lpcbNeeded)
Для получения списка имен драйверов служит функция GetDeviceDriverBaseNameA(lp : pointer; lpBaseName : lpstr; nSize : DWORD). Она получает адрес загруженного драйвера (первый аргумент) и размер имени драйвера (третий аргумент) и возвращает имя драйвера. Пример вызова функции
var
pdriver : array [1..138] of cardinal;
lpcbNeeded : dword;
i : integer;
basename : lpstr;
for I := 1 to lpcbneeded div 4 do
begin
getmem(basename,50);
GetDeviceDriverBaseNameA(pointer(pdriver[i]), BaseName, 50);
1.1.6. Использование функции NtQuerySystemInformation
1.1.6.1. Назначение аргументов функции
Функция NtQuerySystemInformation - cамая известная из более чем 300 функций базового интерфейса ОС Windows, называемого Native API (естественный API). Внешняя часть Native API пользовательского режима содержится в модуле (динамической библиотеке) ntdll.dll, «настоящий» интерфейс реализован в ntoskernel.exe – ядре операционной системы NT (NT operation system kernel). Native API используется для доступа к содержимому многих важных внутренних структур операционной системы, таких как списки процессов, потоков, дескрипторов, драйверов и т. п.
Достоинство функции в том, что для своего выполнения она не требует привилегий администратора.
Прототип этой функции отсутствует в файле windows.pas, поэтому в программе необходимо описать функцию, используя, например, неявный способ ее загрузки из библиотеки DLL, как показано ниже
function NtQuerySystemInformation (
SystemInformationClass: LongInt; // класс запрашиваемой системной информации
SystemInformation: Pointer; // указатель на результирующий буфер
SystemInformationLength: ULONG; // размер этого буфера
ReturnLength: PDWORD // количество записанных байт
) : NTSTATUS; stdcall;
external 'ntdll.dll'; // имя библиотеки DLL, содержащей функцию
Рассмотрим назначение параметров, передаваемых при вызове функции.
Первый параметр определяет класс запрашиваемой системной информации. Например, для получения информации о процессах и потоках первый параметр должен иметь значение 5. Другие возможные значения первого параметра приведены ниже.
// SYSTEM INFO CLASSES
SystemBasicInformation 0
SystemProcessorInformation 1
SystemPerformanceInformation 2
SystemTimeOfDaylnformation, 3
SystemProcessesAndThreadsInformation 5
SystemCallCounts 6
SystemConfigurationlnformation 7
SystemProcessorTimes 8
SystemGlobalFlag 9
SystemModuleInformation 11
SystemObjectInformation, 17
SystemPagefileInformation 18
SystemProcessorStatistics 23
Второй параметр определяет область памяти, в которую функция записывает результат запроса.
Структура буфера зависит от значения первого параметра. Ниже приведено (для справки и практического использования в курсовой работе) описание структур и типов возвращаемых и сопутствующих данных.
Все приведенные ниже описания типов данных должны быть использованы в программе.
type
USHORT = Word; LONG = LongInt;
PLARGE_INTEGER = ^LARGE_INTEGER;
PPWideChar = ^PWideChar; PLONG = ^LongInt;
ULONGLONG = Int64;
PTOKEN_PRIVILEGES = PTokenPrivileges;
TIMER_TYPE = Integer; PUSHORT = ^USHORT;
NTSTATUS = Integer; PVOID = Pointer;
CLIENT_ID = packed record
UniqueProcess: THandle; UniqueThread: THandle;
end;
PCLIENT_ID = ^CLIENT_ID;
{ Структура UNICODE_STRING - Передача строковых параметров для Native API и хранение строк во внутренних структурах Windows }
TUnicodeString = packed record
Length: WORD; MaximumLength: WORD;
Buffer: PWideChar;
end;
UNICODE_STRING = TUnicodeString;
{Базовая информация о системе – класс запрашиваемой информации 0}
SYSTEM_BASIC_INFORMATION = packed record
AlwaysZero: ULONG; MaximumIncrement: ULONG;
PhysicalPageSize: ULONG; NumberOfPhysicalPages: ULONG;
LowestPhysicalPage: ULONG; HighestPhysicalPage: ULONG;
AllocationGranularity: ULONG; LowestUserAddress: ULONG;
HighestUserAddress: ULONG; ActiveProcessors: ULONG;
NumberProcessors: UCHAR; Filler: array[0..2] of char;
end;
type
{Формат времени (структура аналогична SYSTEMTIME в Win32 }
TIME_FIELDS = packed record
Year: WORD; Month: WORD;
Day: WORD; Hour: WORD;
Minute: WORD; Second: WORD;
Milliseconds: WORD; Weekday: WORD;
end;
PTIME_FIELDS = ^TIME_FIELDS;
{ Информация о производительности системы - класс информации равен 2}
SYSTEM_PERFORMANCE_INFORMATION = packed record
IdleTime: LARGE_INTEGER;
ReadTransferCount: LARGE_INTEGER;
WriteTransferCount: LARGE_INTEGER;
OtherTransferCount: LARGE_INTEGER;
ReadOperationCount: ULONG; WriteOperationCount: ULONG;
OtherOperationCount: ULONG; AvailablePages: ULONG;
TotalCommittedPages: ULONG; TotalCommitLimit: ULONG;
PeakCommitment: ULONG; PageFaults: ULONG;
WriteCopyFaults: ULONG; TransitionFaults: ULONG;
Reserved1: ULONG; DemandZeroFaults: ULONG;
PagesRead: ULONG; PageReadIos: ULONG;
Reserved2: array[0..1] of ULONG;
PageFilePagesWritten: ULONG; PageFilePageWriteIos: ULONG;
MappedFilePagesWritten: ULONG;
MappedFilePageWriteIos: ULONG;
PagedPoolUsage: ULONG; NonPagedPoolUsage: ULONG;
PagedPoolAllocs: ULONG; PagedPoolFrees: ULONG;
NonPagedPoolAllocs: ULONG; NonPagedPoolFrees: ULONG;
TotalFreeSystemPtes: ULONG; SystemCodePage: ULONG;
TotalSystemDriverPages: ULONG;
TotalSystemCodePages: ULONG;
SmallNonPagedLookasideListAllocateHits: ULONG;
SmallPagedLookasideListAllocateHits: ULONG;
Reserved3: ULONG; MMSystemCachePage: ULONG;
PagedPoolPage: ULONG; SystemDriverPage: ULONG;
FastReadNoWait: ULONG; FastReadWait: ULONG;
FastReadResourceMiss: ULONG; FastReadNonPossible: ULONG;
FastMdlReadNoWait: ULONG; FastMdlReadWait: ULONG;
FastMdlReadResourceMiss: ULONG;
FastMdlReadNonPossible: ULONG; MapDataNoWait: ULONG;
MapDataWait: ULONG; MapDataNoWaitMiss: ULONG;
MapDataWaitMiss: ULONG; PinMappedDataCount: ULONG;
PinReadNoWait: ULONG; PinReadWait: ULONG;
PinReadNoWaitMiss: ULONG; PinReadWaitMiss: ULONG;
CopyReadNoWait: ULONG; CopyReadWait: ULONG;
CopyReadNoWaitMiss: ULONG; CopyReadWaitMiss: ULONG;
MdlReadNoWait: ULONG; MdlReadWait: ULONG;
MdlReadNoWaitMiss: ULONG; MdlReadWaitMiss: ULONG;
ReadAheadIos: ULONG; LazyWriteIos: ULONG;
LazyWritePages: ULONG; DataFlushes: ULONG;
DataPages: ULONG; ContextSwitches: ULONG;
FirstLevelTbFills: ULONG; SecondlevelTbFills: LONG;
SystemCalls: ULONG;
end;
PSYSTEM_PERFORMANCE_INFORMATION = ^SYSTEM_PERFORMANCE_INFORMATION;
{Информация о текущем времени и часовом поясе класс информации 3 }
SYSTEM_TIME_OF_DAY_INFORMATION = packed record
BootTime: LARGE_INTEGER;
CurrentTime: LARGE_INTEGER; TimeZoneBias: LARGE_INTEGER;
CurrentTimeZoneId: ULONG; Reserved: ULONG;
end;
PSYSTEM_TIME_OF_DAY_INFORMATION = ^SYSTEM_TIME_OF_DAY_INFORMATION;
{ Информация о процессах и потоках }
THREAD_STATE = Integer; KWAIT_REASON = Integer;
KPRIORITY = Integer; POOL_TYPE = Integer;
{ Описание потока }
SYSTEM_THREADS = packed record
KernelTime: LARGE_INTEGER; UserTime: LARGE_INTEGER;
CreateTime: LARGE_INTEGER; WaitTime: ULONG;
StartAddress: PVOID; ClientId: CLIENT_ID;
Priority: KPRIORITY; BasePriority: KPRIORITY;
ContextSwitchCount: ULONG; State: THREAD_STATE;
WaitReason: KWAIT_REASON; Reserved: ULONG;
end;
SYSTEM_THREADS_ARRAY = array[0..1024] of SYSTEM_THREADS;
PSYSTEM_THREADS_ARRAY=SYSTEM_THREADS_ARRAY;
{ Счетчики виртуальной памяти }
VM_COUNTERS = packed record
PeakVirtualSize: ULONG; VirtualSize: ULONG;
PageFaultCount: ULONG; PeakWorkingSetSize: ULONG;
WorkingSetSize: ULONG;QuotaPeakPagedPoolUsage: ULONG;
QuotaPagedPoolUsage: ULONG;
QuotaPeakNonPagedPoolUsage: ULONG;
QuotaNonPagedPoolUsage: ULONG;
PageFileUsage: ULONG; PeakPageFileUsage: ULONG;
end;
{Счетчики ввода-вывода. Эта структура существует только в Windows 2000 и выше}
IO_COUNTERS = packed record
ReadOperationCount: LARGE_INTEGER;
WriteOperationCount: LARGE_INTEGER;
OtherOperationCount: LARGE_INTEGER;
ReadTransferCount: LARGE_INTEGER;
WriteTransferCount: LARGE_INTEGER;
OtherTransferCount: LARGE_INTEGER;
end;
{ Информация о процессе для Windows 2000 и выше }
SYSTEM_PROCESSES_NT2000 = packed record
// величина смещения для перехода к следующему элементу списка
NextEntryDelta: ULONG; ThreadCount: ULONG;
Reserved1: array[0..5] of ULONG;
CreateTime: LARGE_INTEGER;
UserTime: LARGE_INTEGER;
KernelTime: LARGE_INTEGER;
ProcessName: UNICODE_STRING; BasePriority: KPRIORITY;
ProcessId: ULONG; InheritedFromProcessId: ULONG;
HandleCount: ULONG; Reserved2: array[0..1] of ULONG;
VmCounters: VM_COUNTERS; PrivatePageCount: ULONG;
IoCounters: IO_COUNTERS;
//Threads : array[0..0] of SYSTEM_THREADS;
end;
PSYSTEM_PROCESSES_NT2000 = ^SYSTEM_PROCESSES_NT2000;
{Информация об аппаратной конфигурации системы – класс информации 7}
SYSTEM_CONFIGURATION_INFORMATION = packed record
DiskCount: ULONG; FloppyCount: ULONG;
CdRomCount: ULONG; TapeCount: ULONG;
SerialCount: ULONG; ParallelCount: ULONG;
end;
PSYSTEM_CONFIGURATION_INFORMATION = ^SYSTEM_CONFIGURATION_INFORMATION;
{Информация о времени работы процессора в различных режимах. Для каждого процессора в системе возвращается по структуре }
SYSTEM_PROCESSOR_TIMES = packed record
IdleTime: LARGE_INTEGER; KernelTime: LARGE_INTEGER;
UserTime: LARGE_INTEGER; DpcTime: LARGE_INTEGER;
InterruptTime: LARGE_INTEGER; InterruptCount: ULONG;
end;
PSYSTEM_PROCESSOR_TIMES = ^SYSTEM_PROCESSOR_TIMES;
{ Информация о глобальных настройках системы }
SYSTEM_GLOBAL_FLAG = packed record
GlobalFlag: ULONG;
end;
PSYSTEM_GLOBAL_FLAG = ^SYSTEM_GLOBAL_FLAG;
{ Информация о загруженных модулях режима ядра }
SYSTEM_MODULE_INFORMATION = packed record
Reserved: array [0..1] of ULONG;
Base: PVOID; Size: ULONG;
Flags: ULONG; Index: USHORT;
Unknown: USHORT; LoadCount: USHORT;
ModuleNameOffset: USHORT;
ImageName: array[0..255] of char; { ANSI }
end;
PSYSTEM_MODULE_INFORMATION = ^SYSTEM_MODULE_INFORMATION;
SYSTEM_MODULE_INFORMATION_ARRAY = array[0..16384] of SYSTEM_MODULE_INFORMATION;
{ Массив информации для класса SystemModuleInformation }
SYSTEM_MODULES_INFORMATION = packed record
Count: ULONG;
Data: SYSTEM_MODULE_INFORMATION_ARRAY;
end;
PSYSTEM_MODULES_INFORMATION = ^SYSTEM_MODULES_INFORMATION;
{ Информация о дескрипторе }
SYSTEM_HANDLE_INFORMATION = packed record
PID: ULONG; { Идентификатор процесса, владеющего данным дескриптором }
ObjectType: UCHAR; { Тип объекта, идентифицируемого данным дескриптором }
Flags: UCHAR; { Флаги дескриптора }
Handle: USHORT; { Значение дескриптора }
FObject: PVOID; { Адрес объекта, идентифицируемого данным дескриптором }
GrantedAccess: ACCESS_MASK; { Степень доступа к объекту, предоставленная в момент создания данного дескриптора }
end;
PSYSTEM_HANDLE_INFORMATION = ^SYSTEM_HANDLE_INFORMATION;
SYSTEM_HANDLE_INFORMATION_ARRAY = array[0..16384] of SYSTEM_HANDLE_INFORMATION;
{ Массив информации для класса SystemHandleInformation }
SYSTEM_HANDLES_INFORMATION = packed record
Count: ULONG;
Data: SYSTEM_HANDLE_INFORMATION_ARRAY;
end;
PSYSTEM_HANDLES_INFORMATION = ^SYSTEM_HANDLES_INFORMATION;
{ Информация об объектах выдается только в том случае, если в системе установлен глобальный флаг FLG_MAINTAIN_ OBJECT_TYPELIST }
{ Информация об объектах }
SYSTEM_OBJECT_INFORMATION = packed record
NextEntryOffset: ULONG; ObjectAddress: PVOID;
CreatorProcessId: ULONG; Unknown: USHORT;
Flags: USHORT; PointerCount: ULONG;
HandleCount: ULONG; PagedPoolUsage: ULONG;
NonPagedPoolUsage: ULONG; ExclusiveProcessId: ULONG;
SecurityDescriptor: PSECURITY_DESCRIPTOR;
Name: UNICODE_STRING;
end;
Как видно из приведенного описания, информация о процессах и потоках передается в буфере, содержащем структуры данных переменной длины. Каждый процесс представлен структурой, состоящей из общих данных фиксированного размера, и данных переменной длины (описания потоков процесса). Для перехода от первого процесса ко второму и последующим используется поле NextEntryDelta: ULONG, содержимое которого необходимо прибавить к текущему значению указателя SystemInformation.
Цикл просмотра завершается, когда значение поля NextEntryDelta станет равным нулю.
Рисунок 1 Структура информации о процессах и потоках