Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Вопросы и ответы по ОС.doc
Скачиваний:
37
Добавлен:
27.08.2019
Размер:
3.35 Mб
Скачать

Разделы адресного пространства процесса (32 разряда)

Верхнюю половину памяти (от 2 Гбайт до 4 Гбайт) система использует для своих нужд. Сюда она грузит свое ядро (kernel) и драйверы устройств. При попытке обратиться к адресу памяти из этого диапазона возникает исключительная ситуация нарушения доступа и система закрывает приложение. Заметьте, что половину памяти у нас отняли только из-за того, что иначе не удалось добиться совместимости с процессором MIPS R4000, которому нужна память именно из этого раздела.

Следующий небольшой раздел (64 К) также резервируется системой, но никак ей не используется. При попытке обращения к этой памяти возникает нарушение доступа, но приложение не закрывается. Система просто выдает сообщение об ошибке. Следующие (почти) 2 Гбайт отданы в собственность процесса. Сюда загружаются исходный код приложения (ехе-модуль), динамические библиотеки (dll), здесь также располагаются стеки потоков и области heap, в которых они черпают динамически выделяемую память. Последний маленький (64 К) раздел, так же как и третий раздел, не используется системой.

Любому Wm,32-процессу могут понадобиться объекты ядра Windows, а также ее подсистемы User или GDI. Они расположены в динамически подключаемых библиотеках: Kernel32.dll, User32.dll, Gdi32.dll и Advapi32.dll Эти библиотеки при необходимости подгружаются в верхнюю часть блока, доступного процессу.

Верхняя часть виртуального адресного пространства процесса, в которой находятся системные DLL, в Windows NT содержит не сами эти DLL, а только модули-заглушки. Обращение процесса к системе происходит в пределах адресного пространства процесса. Но такое обращение попадает к модулю-заглушке, который формирует сообщение-запрос к подсистеме-серверу на выполнение системного вызова. Средства вызова локальных процедур передают это сообщение процессу-серверу, они же передают ответ сервера в модуль-заглушку, а тот формирует отклик на системный вызов. У пользовательского процесса, таким образом, создается впечатление, что системный вызов был выполнен в пределах его адресного пространства, но если пользовательский процесс испортит верхнюю часть доступного ему адресного пространства, то он испортит только свои модули-заглушки и никак не повлияет на работу других процессов.

Таким образом, в адресном пространстве каждого процесса содержится множество самых разных элементов, в том числе:

  1. образ ЕХЕ-файла программы;

  2. все несистемные DLL, загруженные Вашей программой (включая DLL-модули MFC), глобальные данные программы (доступные как по чтению и записи, так и только по чтению);

  3. стек программы;

  4. динамически выделяемая память, в том числе кучи Windows и библиотеки С периода выполнения;

  5. файлы, спроецированные в память;

  6. блоки памяти, совместно используемые несколькими процессами;

  7. память, локальная для данного выполняемого потока;

  8. особые системные блоки памяти, в том числе таблицы виртуальной памяти;

  9. ядро и DLL-компоненты Windows.

Выделение памяти процессу и освобождение им памяти. Связь функций выделения памятью стандартной библиотеки и системных вызовов, необходимость менеджера памяти режима пользователя

Куча Windows

Куча (heap) – это пул памяти какого-либо процесса. Когда программе требуется блок памяти, она вызывает функцию, выделяющую память из кучи, а чтобы освободить ранее выделенную память, – функцию, парную первой. Выравнивание по границам, кратным 4 Кб, в этом случае не производится; диспетчер кучи использует пространство на выделенных ранее страницах или обращается к VirtualAlloc, чтобы получить дополнительные страницы. Одна из двух куч, с которыми программа работает, – куча Windows. Для выделения из нее памяти служит функция HeapAlloc, а для освобождения – функция HeapFree. HeapAlloc особенно удобна для выделения "крупных" блоков памяти.

Куча библиотеки С периода выполнения, _heapmin и С++-операторы new и delete

Однако, куча Windows (и функция HeapAlloc) – это не та куча, с которой приложение будете работать чаще всего. Существует еще одна куча – ею управляет библиотека С периода выполнения (С RunTime library, CRT). Доступ к CRT-куче реализуется функциями malloc и free, напрямую вызываемыми операторами C++ new и delete. Эта куча оптимизирована для выделения блоков малого размера.

Конечно, функция malloc вызывает VirtualAlloc, но делает это очень хитро. При первом вызове она резервирует регион размером 1 Мб (в будущих версиях Visual C++ эти значения могут измениться) и передает блок памяти, размер которого кратен 64 Кб (если malloc вызван чтобы выделить память размером 64 Кб или менее, выделяется один 64-килобайтный блок). При последующих вызовах память выделяется по возможности из этого блока; в ином случае диспетчер кучи вызывает VirtualAlloc, чтобы передать дополнительную память. После того, как весь регион размером 1 Мб израсходован, malloc резервирует еще один регион размер 2 Мб, потом другой, но уже размером 4 Мб и т.д., передавая память по мере необходимости.

При вызове функции free диспетчер кучи помещает дескрипторы блоков памяти в односвязный циклический список свободных блоков памяти (free list), находящийся вне CRT кучи. Функция malloc использует этот список для последующего выделения памяти (если это возможно). Так как данный список весьма компактен, поиск свободных страниц ocyществляется быстро, без просмотра большого числа страниц виртуальной памяти.

Если процесс выделил много памяти из CRT-кучи, а потом освободил большую часть этой памяти, все страницы остаются переданными. Хотя оперативная память при этом может быть и не выделена, процесс занимает страницы в файле подкачки, которые остаются недоступными другим процессам. При вызове другой CRT-функции, _heapmin, диспетчер кучи возвращает все свободные страницы и, более того, освобождает любые, полностью возвращенные регионы.

10. Отображаемые в память файлы. Их использование ядром ОС при создании процесса (с использованием динамической линковки) и при динамической загрузке библиотек. Использование отображаемых файлов прикладной программой для повышения производительности. Проблема перемещаемых символов и её решение.

Если мы имеем виртуальную память, то используя аналогичный механизм, мы можем построить и обращение к файлу. Обработчик отказа страницы в ядре способен прочитать данную страницу из файла. Концептуально это - то же, что выделение памяти и чтение в нее отрезка файла, с той разницей, что чтение осуществляется неявно "по требованию", выраженному отказом страницы при попытке обращения к ней. При работе с такими видами файлов, физическая память не выделяется из страничного файла, а берется из файла, уже находящегося на диске.

Преимущества такого подхода:

  • в случае отображения "только для чтения" - разделение одной и той же физической памяти между всеми процессами, отображающими данный файл (выделенная же память своя у каждого процесса).

  • Возможность "забывания" (discard) некоторых отображенных страниц без выгрузки их в область подкачки, обязательной для выделенной памяти. В случае повторной потребности в странице она может быть быстро загружена из файла снова.

  • Не использование дискового кэша в этом режиме, что означает экономию на копировании данных из кэша в запрошенный регион.

Преимущества дискового кэша, оптимизирующего операции небольшого размера, а также повторное чтение одних и тех же данных, полностью исчезают при чтениях целых страниц и тем более их групп, недостаток же в виде обязательного лишнего копирования - сохраняется. Отображаемые в память файлы используется в ОС Windows, а также ОС семейства UNIX, для загрузки исполняемых модулей и динамических библиотек.

Несмотря на простую идею, все не так просто при работе с файлом на запись:

  1. Как сделать отображение на не созданный файл – не известен его размер. Если мы выполняем перемещение данных из какого-то адреса в переменную, значит ли это, что файл имеет этот размер. Если в памяти был 0, и туда пишется 0, то мы не узнаем, изменились ли данные.

  2. Допустим, данные записаны по большому адресу. Хранить на диске 4 ГБ нулей не хочется. Как строить этот файл. В разных ОС применяются разные стратегии.

Защищенность информации – это одно из свойств, накладываемых на ФС. Если есть 2 приложения, имеющие одновременно доступ к файлу, то функционирование обоих может быть нарушено.

Например, есть 2 пользователя имеющие одинаковый доступ к файлу, но изменения одного пользователя и не позволяют второму выполнить свои действия. Поэтому в ФС выполняется изоляция изменений информации. Если нет такой изоляции, то мы не можем реализовать целые наборы функциональности.

Стратегия Unix: открыли 10 пользователей один файл – кто последний вышел, тот и сохранил.

Стратегия в Nowell: попытаться сохранить все изменения.

Стратегия в Arix: ведется журналирование. Оно может быть с фиксацией, может быть без нее, для фиксации изменений мы должны указать механизм обработки коллизий.