
Именование объектов. Разделяемые ресурсы
Многие объекты в системе имеют имена. Именование объектов удобно для учета объектов и поиска нужного объекта. Кроме того, знание имени объекта может быть использовано процессом для получения к нему доступа (совместное использование ресурсов). Пространство имен объектов по аналогии с пространствами имен реестра и файлов организовано в виде древовидной иерархической системы. В качестве нетерминальной вершины дерева используется объект - "каталог объектов". Каталог включает информацию, необходимую для трансляции имен объектов в указатели на сами объекты. Вследствие необходимости выполнения навигации по каталогам ссылка на объект по имени работает существенно дольше, чем по описателю.
"Увидеть" пространство имен можно только при помощи специальных инструментальных средств, например, с помощью утилиты winobj, входящей в состав MS Platform SDK. Другую версию этой утилиты можно бесплатно получить на сайте www.sysinternals.com.
Рис. 4.4. Окно утилиты winobj
Прогон программы, создающей объект
В качестве самостоятельного упражнения рекомендуется осуществить прогон программы, создающей один или несколько объектов, появление которых можно проконтролировать с помощью утилиты 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 этого параметра не имеет. Собственного имени файла вполне достаточно для его идентификации и разделения, а пространство имен файлов является продолжением пространства имен объектов (см. рис. 4.5)
Рис. 4.5. Связь пространства имен объектов и пространства имен файловой системы
Совместное использование объектов
Иногда у приложений возникает необходимость в разделении ресурсов. В ОС Windows обычно это имеет следствием совместное использование объектов, стоящих за этими ресурсами.
Наиболее распространенный вариант - когда двум или более процессам известно имя разделяемого объекта. В этом случае один из процессов создает объект (например, с помощью функции CreateSemaphore), а остальные открывают его для себя (например, с помощью функции OpenSemaphore).
Рис. 4.6. Совместное использование объектов
Другим способом получения доступа к уже существующему объекту является наследование дочерним процессом объектов родительского процесса. Наконец, можно осуществить дублирование описателя открытого объекта при помощи функции DuplicateHandle.
Система управляет объектами "файл" отлично от других объектов ядра. Объект "файл" содержит указатель текущей позиции в файле. Поэтому каждый вызов функции CreateFile для одного и того же файла приводит к созданию нового объекта "файл" и соответственно - нового описателя объекта. Лишь процедуры дублирования описателей и наследования позволяют получить новый описатель к одному и тому же объекту. Более сложные сценарии создания объектов и дублирования описателей к ним имеются в MSDN
Реестр
Операционная система управляет большим объемом информации, необходимой для ее загрузки и конфигурирования. В ранних версиях Windows эта информация содержалась в различных текстовых файлах с расширением .ini (Win.ini, System.ini и т.д.). Начиная с Windows 95, эта информация хранится в централизованной общесистемной базе данных, называемой реестром (registry). Для просмотра и модификации данных реестра имеются штатные утилиты (regedit или редактор реестра, например), однако рекомендуется это делать с помощью административной консоли управления.
Рис. 4.7. Общий вид редактора реестра
Данные реестра хранятся в виде иерархической древовидной структуры. Каждый узел или каталог называется разделом или ключом (keys), а названия каталогов верхнего уровня начинаются со строки HKEY. Каждый раздел может содержать подраздел (subkey). Записи нижней части структуры называются параметрами (values), данные которых строго типизированы, см. MSDN.
Реестр содержит шесть корневых разделов: HKEY_CURRENT_USER, HKEY__USERS, HKEY_CLASSES_ROOT, HKEY_LOCAL_MACHINE, HKEY_PERFORMANCE_DATA и HKEY_CURRENT_CONFIG. Наиболее важным, вероятно, является раздел HKEY_LOCAL_MACHINE. В нем содержится вся информация о локальной системе.
Пространство имен реестра интегрировано с общим пространством имен ядра. Оно является третьим пространством имен в системе наряду с пространствами имен объектов и файлов. Для интеграции система поддерживает объект "раздел реестра" (key есть среди типов объектов).
Реестр хранится на диске в виде набора файлов, называемых "кустами" или "ульями" (hives). Большинство из них находится в каталоге \Systemroot\System32\Config. Большое значение уделяется повышению надежности хранения. В частности, система ведет протоколы модификации кустов (при помощи так называемых регистрационных кустов, log hives), которые обеспечивают гарантированную возможность восстановления постоянных кустов реестра. Для еще большей защиты целостности на диске поддерживаются зеркальные копии критически важных кустов. Структура кустов подробно описана в [6], а их описатели можно просмотреть с помощью утилиты Handleex.exe с сайта www.sysinternals.com.
Данные реестра полностью доступны через Win32 API. Существуют вызовы для просмотра, создания и удаления разделов и параметров. Чтобы получить доступ к данным, нужно (при наличии необходимых привилегий) открыть соответствующий раздел с помощью функции RegOpenKeyEx. Для записи или удаления можно использовать функции RegSetValue, RegDeleteValue. Более подробно работа с данными реестра описана в MSDN и в [4], [5].