Операционные системы. Управление ресурсами

       

Общие области памяти


Два и более процессов могут использовать одну и ту же физическую область памяти. Наиболее просто это достигается в тех моделях памяти, которые обеспечивают динамическую трансляцию адресов. Напомним, что каждый процесс имеет собственную таблицу сегментов или страниц, в которой содержится, помимо прочего, базовый адрес сегмента/страницы в физической памяти. Для разделяемой области памяти создается по элементу в таблице для каждого процесса, ее использующего. В чисто страничной модели, однако, возникают трудности, связанные с тем, что разделяемая область памяти может иметь объем, некратный размеру страницы, обычно в таких случаях разделяемая область выравнивается до границы страницы. В сегментной или сегментно-страничной модели таких проблем нет. Поскольку для каждого процесса разделяемый сегмент описывается своим дескриптором, права доступа к сегменту могут быть установлены различными для разных процессов.

В случае именованных областей памяти один процесс создает общую область памяти:

vAddr = createNamedMemorySegment(segmentName, segmentSize);

а второй ее "открывает":

vAddr = openNamedMemorySegment(segmentName);

В этих вызовах segmentName - имя области, segmentSize - ее размер. Оба вызова возвращают виртуальный адрес общей области памяти в виртуальном адресном пространстве процесса - vAddr.

Для неименованной области памяти создание области осуществляется вызовом:

vAddr = createMemorySegment(segmentSize);

а "открытие":

vAddr = openMemorySegment(hostAddr, hostPid);

где hostAddr - виртуальный адрес области памяти у процесса-создателя области, hostPid - идентификатор процесса-создателя области. Этот вызов возвращает виртуальный адрес области в адресном пространстве процесса, открывшего область.

Разумеется, в составе API имеются системные вызовы "закрытия"/уничтожения общей области памяти.

Разделяемые области памяти, однако, порождают ряд проблем как для программистов, так и для ОС. Проблемы программистов - те, что рассматривались в предыдущем разделе: взаимное исключение процессов при доступе к общей памяти.
Программисты могут дифференцировать права доступа для процессов или организовать взаимное исключение, используя семафоры (см. ниже). Проблемы ОС - организация свопинга. Очевидно, что вероятность вытеснения разделяемого сегмента или страницы должна быть тем меньше, чем больше процессов разделяют этот сегмент/страницу. Если каждый процесс имеет собственный дескриптор разделяемого сегмента или страницы, то учет использования сегмента или страницы (поля used и dirty) будут вестись по каждому процессу отдельно. ОС должна обрабатывать, например, такой случай: два процесса - A и B - разделяют сегмент; процесс A произвел запись в сегмент и в его дескрипторе сегмент помечен, как "грязный". В то время, когда активен процесс B, принимается решение о вытеснении этого сегмента из памяти. Но в дескрипторе процесса B этот сегмент имеет признак "чистый", поэтому сегмент может быть освобожден в физической памяти без сохранения на внешней памяти и изменения в сегменте, сделанные процессом A, будут утеряны. ОС приходится вести отдельную таблицу разделяемых сегментов, в которой отражать истинное их состояние.

С точки зрения идентификации разделяемые области памяти могут рассматриваться как виртуальные коммуникационные порты. Для общей области может быть по соглашению между разработчиками взаимодействующих процессов установлено внешнее имя, которое будет использовано для получения доступа. (В Windows 95, например, такие области называются "файлами отображаемой памяти" - memory mapped file - и для установления доступа к ним используются системные вызовы типа create и open). Для неименованных областей памяти возможна передача селектора (номера в таблице дескрипторов) от одного процесса к другому.

В системах, которые ориентированы на процессор Intel-Pentium, может использоваться то обстоятельство, что адресация возможна через две таблицы дескрипторов - LDT и GDT. За счет этого общее адресное пространство процесса может достигать 4 Гбайт. Из них младшие 2 Гбайт адресуются через LDT а старшие - через GDT.Глобальная таблица дескрипторов - общая для всех процессов, и именно она может использоваться для доступа к совместно используемой памяти. Размещение в общих виртуальных адресах удобно для системных программ и динамических библиотек, к которым происходят частые обращения из приложений: если эти компоненты ОС находятся в адресном пространстве процесса, то обращения к ним не требуют переключения контекста. Но с другой стороны, это снижает надежность: если системные компоненты доступны для приложения, то они могут быть им испорчены. Поэтому такая "роскошь" может быть допущена только в однопользовательских системах.




Содержание раздела