Архитектура операционной системы UNIX (ЛП) - Бах Морис Дж.
Шрифт:
Интервал:
Закладка:
алгоритм freereg /* освобождение выделенной области */
входная информация: указатель на (заблокированную) область
выходная информация: отсутствует
{
if (счетчик ссылок на область имеет ненулевое значение) {
/* область все еще используется одним из процессов */
снять блокировку с области;
if (область ассоциирована с индексом) снять блокировку с индекса;
return;
}
if (область ассоциирована с индексом) освободить индекс (алгоритм iput);
освободить связанную с областью физическую память;
освободить связанные с областью вспомогательные таблицы;
очистить поля области;
включить область в список свободных областей;
снять блокировку с области;
}
Рисунок 6.25. Алгоритм освобождения области
6.5.6 Освобождение области
Если область не присоединена уже ни к какому процессу, она может быть освобождена ядром и возвращена в список свободных областей (Рисунок 6.25). Если область связана с индексом, ядро освобождает и индекс с помощью алгоритма iput, учитывая значение счетчика ссылок на индекс, установленное в алгоритме allocreg. Ядро освобождает все связанные с областью физические ресурсы, такие как таблицы страниц и собственно страницы физической памяти. Предположим, например, что ядру нужно освободить область стека, описанную на Рисунке 6.22. Если счетчик ссылок на область имеет нулевое значение, ядро освободит 7 страниц физической памяти вместе с таблицей страниц.
алгоритм detachreg /* отсоединить область от процесса */
входная информация: указатель на точку входа в частной таблице областей процесса
выходная информация: отсутствует
{
обратиться к вспомогательным таблицам процесса, имеющим отношение к распределению памяти, освободить те из них, которые связаны с областью;
уменьшить размер процесса;
уменьшить значение счетчика ссылок на область;
if (значение счетчика стало нулевым и область не является неотъемлемой частью процесса)
освободить область (алгоритм freereg);
else { /* либо значение счетчика отлично от 0, либо область является неотъемлемой частью процесса */
снять блокировку с индекса (ассоциированного с областью);
снять блокировку с области;
}
}
Рисунок 6.26. Алгоритм отсоединения области
6.5.7 Отсоединение области от процесса
Ядро отсоединяет области при выполнении системных функций exec, exit и shmdt (отсоединить разделяемую память). При этом ядро корректирует соответствующую запись и разъединяет связь с физической памятью, делая недействительными связанные с областью регистры управления памятью (алгоритм detachreg, Рисунок 6.26). Механизм преобразования адресов после этого будет относиться уже к процессу, а не к области (как в алгоритме freereg). Ядро уменьшает значение счетчика ссылок на область и значение поля, описывающего размер процесса в записи таблицы процессов, в соответствии с размером области. Если значение счетчика становится равным 0 и если нет причины оставлять область без изменений (область не является областью разделяемой памяти или областью команд с признаками неотъемлемой части процесса, о чем будет идти речь в разделе 7.5), ядро освобождает область по алгоритму freereg. В противном случае ядро снимает с индекса и с области блокировку, установленную для того, чтобы предотвратить конкуренцию между параллельно выполняющимися процессами (см. раздел 7.5), но оставляет область и ее ресурсы без изменений.
6.5.8 Копирование содержимого области
Рисунок 6.27. Копирование содержимого области
алгоритм dupreg /* копирование содержимого существующей области */
входная информация: указатель на точку входа в таблице областей
выходная информация: указатель на область, являющуюся точной копией существующей области
{
if (область разделяемая) /* в вызывающей программе счетчик ссылок на область будет увеличен, после чего будет исполнен алгоритм attachreg */
return (указатель на исходную область);
выделить новую область (алгоритм allocreg);
установить значения вспомогательных структур управления памятью в точном соответствии со значениями существующих структур исходной области;
выделить для содержимого области физическую память;
«скопировать» содержимое исходной области во вновь созданную область;
return (указатель на выделенную область);
}
Рисунок 6.28. Алгоритм копирования содержимого существующей области
Системная функция fork требует, чтобы ядро скопировало содержимое областей процесса. Если же область разделяемая (разделяемый текст команд или разделяемая память), ядру нет надобности копировать область физически; вместо этого оно увеличивает значение счетчика ссылок на область, позволяя родительскому и порожденному процессам использовать область совместно. Если область не является разделяемой и ядру нужно физически копировать ее содержимое, оно выделяет новую запись в таблице областей, новую таблицу страниц и отводит под создаваемую область физическую память. В качестве примера рассмотрим Рисунок 6.27, где процесс A порождает с помощью функции fork процесс B и копирует области родительского процесса. Область команд процесса A является разделяемой, поэтому процесс B может использовать эту область совместно с процессом A. Однако области данных и стека родительского процесса являются его личной принадлежностью (имеют частный тип), поэтому процессу B нужно скопировать их содержимое во вновь выделенные области. При этом даже для областей частного типа физическое копирование области не всегда необходимо, в чем мы убедимся позже (глава 9). На Рисунке 6.28 приведен алгоритм копирования содержимого области (dupreg).
6.6 ПРИОСТАНОВКА ВЫПОЛНЕНИЯ
К настоящему моменту мы рассмотрели все функции работы с внутренними структурами процесса, выполняющиеся на нижнем уровне взаимодействия с процессом и обеспечивающие переход в состояние «выполнения в режиме ядра» и выход из этого состояния в другие состояния, за исключением функций, переводящих процесс в состояние «приостанова выполнения». Теперь перейдем к рассмотрению алгоритмов, с помощью которых процесс переводится из состояния «выполнения в режиме ядра» в состояние «приостанова в памяти» и из состояния приостанова в состояния «готовности к запуску» с выгрузкой и без выгрузки из памяти.