Напомним, что если область при выполнении алгоритма allocreg (Раздел 6.5.2) выделяется впервые, ядро увеличивает значение счетчика ссылок на индекс, ассоциированный с областью, при этом значение счетчика ссылок нами уже было увеличено в самом начале выполнения функции exec (алгоритм namei). Поскольку ядро уменьшает значение счетчика только один раз в завершение выполнения функции exec (по алгоритму iput), значение счетчика ссылок на индекс файла, ассоциированного с разделяемой областью команд и исполняемого в настоящий момент, равно по меньшей мере 1. Поэтому когда процесс разрывает связь с файлом (функция unlink), содержимое файла остается нетронутым (не претерпевает изменений). После загрузки в память сам файл ядру становится ненужен, ядро интересует только указатель на копию индекса файла в памяти, содержащийся в таблице областей; этот указатель и будет идентифицировать файл, связанный с областью. Если бы значение счетчика ссылок стало равным 0, ядро могло бы передать копию индекса в памяти другому файлу, тем самым делая сомнительным значение указателя на индекс в записи таблицы областей: если бы пользователю пришлось исполнить новый файл, используя функцию exec, ядро по ошибке связало бы его с областью команд старого файла. Эта проблема устраняется благодаря тому, что ядро при выполнении алгоритма allocreg увеличивает значение счетчика ссылок на индекс, предупреждая тем самым переназначение индекса в памяти другому файлу. Когда процесс во время выполнения функций exit или exec отсоединяет область команд, ядро уменьшает значение счетчика ссылок на индекс (по алгоритму freereg), если только связь индекса с областью не помечена как «неотъемлемая».
алгоритм xalloc /* выделение и инициализация области команд */
входная информация: индекс исполняемого файла
выходная информация: отсутствует
{
if (исполняемый файл не имеет отдельной области команд)
return;
if (уже имеется область команд, ассоциированная с индексом исполняемого файла)
{
/* область команд уже существует… подключиться к ней */
заблокировать область;
do while (содержимое области еще не доступно)
{
/* операции над счетчиком ссылок, предохраняющие от глобального удаления области */
увеличить значение счетчика ссылок на область;
снять с области блокировку;
sleep (пока содержимое области не станет доступным);
заблокировать область;
уменьшить значение счетчика ссылок на область;
}
присоединить область к процессу (алгоритм attachreg);
снять с области блокировку;
return;
}
/* интересующая нас область команд не существует — создать новую */
выделить область команд (алгоритм allocreg); /* область заблокирована */
if (область помечена как «неотъемлемая»)
отключить соответствующий флаг;
подключить область к виртуальному адресу, указанному в заголовке файла (алгоритм attachreg);
if (файл имеет специальный формат для системы с замещением страниц) /* этот случай будет рассмотрен в главе 9 */
else /* файл не имеет специального формата */
считать команды из файла в область (алгоритм loadreg);
изменить режим защиты области в записи частной таблицы областей процесса на «read-only»;
снять с области блокировку;
}
Рисунок 7.23. Алгоритм выделения областей команд
Рисунок 7.24. Взаимосвязь между таблицей индексов и таблицей областей в случае совместного использования процессами одной области команд