Лекції "Системне програмування"

3. Лекція 4 Об'єкти. Менеджер об'єктів. Реєстр

Об'єкти. Менеджер об'єктів. Реєстр

Вступ

Для роботи з важливими системними ресурсами ОС Windows створює об'єкти, управління якими здійснює менеджер об'єктів. Коли додаток відкриває файл, створює потік або семафор, він отримує дискриптор, описувач (handle) відповідного об'єкта (див. Мал. 4.1). Наприклад, після виконання програмного оператора

hSemaphore = CreateSemaphore (NULL, 0, MaxCount, "MySemaphore");

що створює семафор, повертається описувач hSemaphore необхідний додатку для подальшої роботи з цим семафором.

 

Об'єкти - абстрактна концепція, яка активно використовується в ОС Windows для регулювання доступу до системних ресурсів.

Наявність об'єктів є безперечною необхідністю системи.

  • Це єдиний інтерфейс до всіх системних ресурсів і структур даних, таких, як процеси, потоки, семафори і т.д.
  • Іменування об'єктів і доступ до них здійснюються по одній схемі.
  • Використання об'єктів дає Microsoft можливість оновлювати функціональність системи, не зачіпаючи програмного інтерфейсу додатків.
  • Це дуже важливо з точки зору системної безпеки. Кожен об'єкт має список прав доступу, який перевіряється щоразу, коли додаток створює свій описувач об'єкта. Відповідно, всі перевірки, пов'язані із захистом, можуть бути виконані в одному модулі - диспетчері об'єктів (відповідно до вимог безпеки), з гарантією, що жоден процес не може їх обійти.
  • Легко організувати спільний доступ до об'єктів, нескладно відстежити об'єкти, які більше не використовуються, і т.д.

Об'єкти присутні майже в усіх компонентах системи, особливо там, де є дані, які потрібно розділяти, захищати, іменувати або зробити доступними. Наприклад, за допомогою об'єктів реалізовані програмні і апаратні переривання, а також багато інших функцій ядра. Деякі об'єкти доступні для користувача додатків через виклики Win32. Тому іноді ОС Windows називають об'єктно-орієнтованої системою, - так, доступ до ресурсу можливий тільки через методи відповідного об'єкта (інкапсуляція даних). Разом з тим в даній схемі відсутні успадкування і поліморфізм, тому ОС Windows не можна вважати об'єктно-орієнтованої в строгому сенсі цього слова.

Об'єкти ядра (kernel objects)

Підтримка об'єктів ядра здійснюється власне ядром і виконавчою системою. Крім об'єктів ядра є також об'єкти, призначені для керування вікнами (User), і об'єкти, призначені для керування графікою (GDI).

Сукупність об'єктів утворює багатошарову структуру. Ядро підтримує базові об'єкти двох видів: об'єкти диспетчера (події, м'ютекси, семафори, потоки ядра, таймери і ін.) і керуючі (DPC, APC, переривання, процеси, профілі та ін.)

Над об'єктами ядра знаходяться об'єкти виконавчої системи, кожен з яких інкапсулює один або більше об'єктів ядра. Об'єкти виконавчої системи призначені для управління пам'яттю, процесами і міжпроцесорним обміном. Вони експортуються в розпорядження користувача додатків через Win32 функції. До них відносяться такі об'єкти, як: процес, потік, відкритий файл, семафор, м'ютекс, маркер доступу і ряд інших. Повний список можна побачити в MSDN. Ці об'єкти і називаються об'єктами ядра в посібниках з програмування.

Зовнішня відмінність об'єктів ядра (об'єктів виконавчої системи) від об'єктів User і GDI складається в наявності у перших атрибутів захисту, які є одним з параметрів, що створюють об'єкт ядра функцій. Далі ці об'єкти ядра (об'єкти виконавчої системи) будуть називатися просто об'єктами.

Об'єкт являє собою блок пам'яті в віртуальному адресному просторі ядра. Цей блок містить інформацію про об'єкт у вигляді структури даних (див. Нижче "структура об'єкта"). Структура містить як загальні, так і специфічні для кожного об'єкта елементи. Об'єкти створюються в процесі завантаження і функціонування ОС і губляться при перезавантаженні і виключенні живлення.

Вміст об'єктів є тільки ядру, додаток не може модифікувати його безпосередньо. Доступ до об'єктів можна здійснити тільки через його функції-методи (інкапсуляція даних), які ініціюються викликами деяких бібліотечних Win32-функцій.

Структура об'єкта. методи об'єкта

Кожен об'єкт має заголовок з інформацією, загальною для всіх об'єктів, а також дані, специфічні для об'єкта. Наприклад, в полі заголовку є список процесів, які відкрили даний об'єкт, і інформація про захист, яка визначає, хто і як може використовувати об'єкт.

Лічильник посилань на об'єкт збільшується на 1 при відкритті об'єкта і зменшується на 1 при його закритті. Значення лічильника посилань, рівне нулю, означає, що об'єкт більше не використовується і розподілений йому адресний простір ядра може бути звільнено. Наявність лічильника означає, що навіть після завершення процесу, який створив об'єкт, цей об'єкт може не бути зруйнований (якщо його лічильник не обнулений).

Квота встановлює обмеження на обсяги ресурсів. Незважаючи на те, що в ОС Windows реалізований код для відстеження квот, в даний час квоти не застосовуються і існують досить м'які обмеження. Наприклад, за замовчуванням ліміт на відкриті об'єкти для процесу - 230. Безліч об'єктів поділяється на типи, а у кожного з об'єктів є атрибути, незмінні для об'єктів даного типу. Посилання на тип об'єкту також входить до складу заголовка. Поля ім'я об'єкта і каталог будуть описані в розділі "іменування об'єктів".

Методи об'єкта

До складу компонентів об'єкта входить атрибут методи - покажчики на внутрішні процедури для виконання стандартних операцій. Методи викликаються диспетчером об'єктів при створенні і знищенні об'єкта, відкриття і закриття описувача об'єкту, зміні параметрів захисту. Система дозволяє динамічно створювати нові типи об'єктів. У цьому випадку передбачається реєстрація його методів в диспетчера об'єктів. Наприклад, метод open викликається щоразу, коли створюється або відкривається об'єкт і створюється його новий описувач.

Описувачі об'єктів

Створення нових об'єктів, або відкриття за ім'ям вже існуючих, додаток може здійснити за допомогою Win32-функцій, таких, як CreateFile, CreateSemaphore, OpenSemaphore і т.д. Це бібліотечні процедури, за якими стоять сервіси Windows і методи об'єктів. У разі успішного виконання створюється 64-бітний описувач в таблиці описувачів процесу в пам'яті ядра. На цю таблицю є посилання з блоку управління процесом EPROCESS.

З 64-х розрядів описувача 29 розрядів використовуються для посилання на блок пам'яті об'єкта ядра, 3 - для прапорів, а що залишилися 32 - в якості маски прав доступу.

Маска прав доступу формується на етапі створення чи відкриття об'єкта, коли виконується перевірка дозволів. Таким чином, описувач об'єкта - приналежність процесу, який створив цей об'єкт. За замовчуванням він не може бути переданий іншому процесу. Проте, система надає можливість дублювання описувач і передачі його іншому процесу спеціальним чином.

Win32-функції, що створюють об'єкт, повертають додатку не сам описувач, а індекс в таблиці описувачів, тобто мале число: типу 1, 2 а не 64-розрядне (див. Рис. 4.3). Надалі це значення передається функціям, які приймають описувач об'єкту у якості аргументу. Однією з таких функцій є функція CloseHandle(), завдання якої - закрити об'єкт. Щоб уникнути витоку пам'яті завжди рекомендується закривати об'єкт, якщо в ньому відпала потреба. Втім, після закінчення роботи процесу система закриває всі його об'єкти. Таким чином, структури об'єктів ядра доступні тільки ядру, додаток не може самостійно знайти ці структури в пам'яті та безпосередньо модифікувати їх вміст.

Іменування об'єктів. колективні ресурси

Багато об'єктів в системі мають імена. Іменування об'єктів зручно для обліку об'єктів і пошуку потрібного об'єкту. Крім того, знання імені об'єкта може бути використано процесом для отримання до нього доступу (спільне використання ресурсів).

Простір імен об'єктів за аналогією з просторами імен реєстру і файлів організовано у вигляді дерева ієрархічної системи. Для вершин дерева використовується об'єкт - "каталог об'єктів". Каталог включає інформацію, необхідну для трансляції імен об'єктів в покажчики на самі об'єкти. Внаслідок необхідності виконання навігації по каталогам посилання на об'єкт по імені працює значно довше, ніж по описувачу.

"Побачити" простір імен можна тільки за допомогою спеціальних інструментальних засобів, наприклад, за допомогою утиліти winobj, що входить до складу MS Platform SDK.

Мал. 4.4. Вікно утиліти winobj

Приклад програми, що створює об'єкт

Прикладом такої програми може бути програма відображення файлу в пам'ять.

#include <windows.h>

#include <stdio.h>

void main (void){

HANDLE hMapFile;

HANDLE hFile;

 

hFile = CreateFile ( "MyFile.txt",

GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,

NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

 

hMapFile = CreateFileMapping (hFile, NULL,

PAGE_READWRITE, 0, 0, "MyFileObject");

getchar();

}

В результаті роботи цієї програми файл "myfile.txt" відображається в пам'ять, при цьому в каталозі об'єктів BaseNamedObjects створюється об'єкт "секція" з ім'ям "MyFileObject".

Імена усіх базових об'єктів, таких, як м'ютекси, проекції файлу в пам'ять, семафори зберігаються в одному каталозі BaseNamedObjects. Тому вони не повинні збігатися навіть у об'єктів різних типів. Обрання одного і того ж імені для різних об'єктів призведе до помилки. Це властивість можна використовувати для запобігання запуску декількох екземплярів додатку, в якому створюється іменований об'єкт.

Іменування допускають не всі об'єкти ядра. Зазвичай функція, що створює іменований об'єкт, має в якості параметра ім'я об'єкта. Наприклад, функція CreateMutex створює іменований об'єкт.

HANDLE CreateMutex (PSECURITY_ATTRIBUTES psa,

  BOOL bInitialOwner, PCTSTR pszName);

Останній параметр pszName і є ім'я (можна створити безіменний об'єкт, якщо вказати тут NULL). Між іншим, об'єкт "відкритий файл" є неіменований, і, отже, функція яка створює цей об'єкт CreateFile цього параметра не має. Власного імені файлу цілком достатньо для його ідентифікації та поділу, а простір імен файлів є продовженням простору імен об'єктів.

Спільне використання об'єктів

Іноді у додатків виникає необхідність у спальному використанні ресурсів.

Найбільш поширений варіант - коли двом або більше процесів відоме ім'я спільного об'єкту. У цьому випадку один з процесів створює об'єкт (наприклад, за допомогою функції CreateSemaphore), а інші відкривають його для себе (наприклад, за допомогою функції OpenSemaphore).

Іншим способом отримання доступу до вже існуючого об'єкта є успадкування дочірнім процесом об'єктів батьківського процесу. Можна здійснити дублювання описувача відкритого об'єкта за допомогою функції DuplicateHandle.

Система керує об'єктами "файл" не так як іншими об'єктами ядра. Об'єкт "файл" містить покажчик поточної позиції у файлі. Тому кожен виклик функції CreateFile для одного і того ж файлу призводить до створення нового об'єкта "файл" і відповідно - нового описувача об'єкта. Лише процедури дублювання описувачів і успадкування дозволяють отримати новий описувач до одного і того ж об'єкту.

Реєстр

Операційна система керує великим об'ємом інформації, необхідної для її завантаження і конфігурації. У ранніх версіях Windows ця інформація містилася в різних текстових файлах з розширенням .ini (Win.ini, System.ini і т.д.).

Починаючи з Windows 95, ця інформація зберігається в централізованій загальносистемної базі даних, реєстрі (registry). Для перегляду і модифікації даних уреєстрі є штатні утиліти (regedit редактор реєстру, наприклад), проте рекомендується це робити за допомогою адміністративної консолі управління.

Мал. 4.7. Загальний вигляд редактора реєстру

Дані реєстру зберігаються у вигляді ієрархічної деревоподібної структури. Кожен вузол або каталог називається розділом або ключем (keys), а назви каталогів верхнього рівня починаються з рядка HKEY. Кожен розділ може містити підрозділ (subkey). Записи нижній частині структури називаються параметрами (values), дані яких строго типізовані, см. MSDN.

Реєстр містить два кореневих розділи:

  • HKEY__USERS
  • HKEY_LOCAL_MACHINE

Ще є посилання на підвузли:

  • HKEY_CURRENT_USER
  • HKEY_CLASSES_ROOT
  • HKEY_PERFORMANCE_DATA
  • HKEY_CURRENT_CONFIG

Найбільш важливим є розділ HKEY_LOCAL_MACHINE. У ньому міститься вся інформація по локальній системі.

Простір імен реєстру інтегровано із загальним простором імен ядра. Воно є третім простором імен в системі поряд з просторами імен об'єктів і файлів. Для інтеграції система підтримує об'єкт "розділ реєстру" (key є серед типів об'єктів).

Реєстр зберігається на диску у вигляді набору файлів, які називаються "кущами" або "вуликами" (hives). Більшість з них знаходиться в каталозі \ Systemroot \ System32\Config. Велике значення приділяється підвищенню надійності зберігання. Зокрема, система веде протоколи модифікації кущів (за допомогою так званих реєстраційних кущів, log hives), які забезпечують гарантовану можливість відновлення постійних кущів реєстру. Для ще більшого захисту цілісності на диску підтримуються дзеркальні копії критично важливих кущів.

Дані реєстру повністю доступні через Win32 API. Існують виклики для перегляду, створення і видалення розділів і параметрів. Щоб отримати доступ до даних, потрібно (при наявності необхідних привілеїв) відкрити відповідний розділ за допомогою функції RegOpenKeyEx. Для запису або видалення можна використовувати функції RegSetValue, RegDeleteValue.