5764

Управление памятью в среде Windows

Реферат

Информатика, кибернетика и программирование

Управление памятью С приходом 32-разрядной Windows управление памятью стало гораздо более приятным, чем раньше. Огромная путаница с сегментами и другими параметрами управления памятью в 16-разрядном режиме сегментной архитектуры Intel-процессоров по...

Русский

2012-12-19

87 KB

39 чел.

Управление памятью

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

Отдельные адресные пространства

Win32 предусматривает более совершенную схему управления памятью. Двумя ее наиболее отличительными чертами являются возможности

запускать приложения в отдельных адресных пространствах 

и расширять объем доступной для выделения памяти, используя файлы подкачки (свопирование).

Адреса, используемые приложениями Win32, часто называются логическими. Для каждого процесса Win32 доступен полный диапазон 32-разрядных адресов (с определенными ограничениями для некоторых операционных систем, причем эти ограничения не одинаковы для разных платформ Win32).

Когда Win32 ссылается на данные по логическому адресу, используется аппаратное обеспечение управления памятью компьютера, которое преобразует этот адрес в физический. Один и тот же логический адрес может (и в большинстве случаев это так и происходит) преобразовываться в разные физические адреса для разных процессов.

Наиболее очевидным преимуществом использования отдельных адресных пространств является то, что процессы больше не могут случайно переписать программный код или данные, принадлежащие другому процессу. Неправильные указатели могут привести к сбою нарушившегося процесса, но уже не могут исказить данные в адресном пространстве другого процесса или операционной системы.

С другой стороны

Тот факт, что процессы больше не делят одного логического адресного пространства, усложняет разработку корпоративных процессов. Теперь невозможно передать адрес какого-то объекта в памяти другому процессу, чтобы то смог воспользоваться этим объектом. Этот адрес имеет смысл только в контексте посылающего приложения; в контексте же принимающего приложения он не имеет никакого смысла и представляет собой случайный участок памяти.

К счастью,

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

Виртуальная память

Не все логические адреса приложения действительно отображаются в физическую память.

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

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

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

Поскольку эта операция поддерживается аппаратным обеспечением процессора, она не требует никакого дополнительного времени для вычисления адреса памяти.

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

Все это остается незаметным для приложения; единственным признаком того, что блок не находился в физической памяти, является задержка, вызванная операцией подкачки.

Неперемещаемая память

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

Блок неперемещаемой памяти характеризуется тем, что как бы он не перемещался физически, его виртуальный адрес остается неизменным.

Отметим, что

Для выделения блоков неперемещаемой памяти в Win32 можно использовать как библиотечные функции C и операторы С++, так и функции Windows, предоставляемые для этих целей системой Win32.

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

 

#define N 256

 

Определим в программе указатель на массив целых чисел следующим образом (указатель p - 32-разрядное число, которое неинициализировано):

 

int *p;

 

Для выделения блоков неперемещаемой памяти и работы с ними рекомендуется использовать обычные библиотечные функции С, так как они просты и привычны.

Можно выделить блок памяти, на который будет указывать p, следующим образом:

 

 p=(int *)malloc(N*sizeof(int)); // или p=(int *)сalloc(N,sizeof(int));

 

При этом  c помощью функции malloc выделяется блок памяти размером 1024 байта (1 КБ), который может хранить 256 32-разрядных целых. Указатель, равный NULL, показывает, что выделение памяти не было успешным.

Можно также выделить такой блок память, используя следующий вызов функции calloc. Два параметра функции calloc перемножаются и в результате получается 1024 байта. Кроме того, функция calloc производит обнуление блока памяти.

Доступ к i-тому элементу массива, хранящегося в блоке памяти, на который ссылается p, осуществляется при помощи операции []:

 

. . . p[i] . . .

 

Если необходимо увеличить размер блока памяти (например, удвоить его), то можно вызвать функцию:

 

 int N_new=N*2;

p=(int *)realloc(p, N_new*sizeof(int));

 

Указатель является параметром функции, и указатель (возможно, отличающийся по значению от первого, особенно, если блок увеличивается) является возвращаемым значением функции realloc. Этот пример показывает, что операционная система может перемещать блок в рамках виртуальной памяти.

После окончания работы с памятью необходимо вызвать функцию, освобождающую блок памяти:

 

free(p);

 

 Замечание. Только указанные четыре функции (malloc, calloc, realloc, free) определены в стандарте ANSI языка C. Часто производители компиляторов реализуют несколько большее количество функций, наиболее распространенной из которых является функция _msize, возвращающая размер выделенного блока.

Помимо библиотечных функций С для выделения блоков неперемещаемой памяти и работы с ними можно использовать и операторы языка C++.

Приведем пример их использования:

 

p=new int[N];   // выделение блока памяти и инициализация указателя

 if(p!=NULL)

{

 . . . p[i] . . . // использование значений элементов массива

 delete []p;   // освобождение блока памяти

}

 

Для выделения блоков неперемещаемой памяти и работы с ними можно использовать вызовы функций ядра Windows. Ниже приведена функция Windows для выделения блока неперемещаемой памяти для указателя на целые:

 

 int *p; // объявление указателя

. . .

p=(int *)GlobalAlloc(GPTR, N*sizeof(int));

 

Функция GlobalAlloc имеет два параметра: набор флагов и размер выделяемого блока в байтах. Если первый параметр функции GlobalAlloc задать нулевым, то это аналогично использованию флага GMEM_FIXED (равен нулю). Такой вызов функции GlobalAlloc эквивалентен вызову функции malloc. Можно также использовать флаг GMEM_ZEROPOINT для обнуления всех байтов выделяемого блока памяти. Флаг GPTR включает в себя флаги GMEM_FIXED и GMEM_ZEROPOINT.

Виртуальный адрес, который выдает функция GlobalAlloc в приведенном примере, может использоваться в программе для доступа к выделенной памяти. Значение NULL говорит о том, что имеющейся в распоряжении памяти для выделения недостаточно.

Для каждой функции (за исключением одной), начинающейся со слова Global, существует другая, начинающаяся со слова Local. Эти два набора в Win32 идентичны. Два различных слова сохранены для совместимости с предыдущими версиями Windows, где функции Global возвращали дальние указатели, а функции Local - ближние.

Доступ к i-тому элементу массива, хранящегося в блоке памяти, на который ссылается p, осуществляется при помощи операции []:

 

. . . p[i] . . .

 

Имеется также функция изменения размера блока памяти:

 

 int N_new=N*2;

p=(int *)GlobalReAlloc(p, N_new*sizeof(int), GMEM_FIXED);

 

Можно использовать флаг GMEM_ZEROPOINT для обнуления добавляющихся в блок памяти байтов, если блок расширяется.

Существует функция, возвращающая размер блока памяти и функция освобождения памяти:

 

 DWORD dwSize=GlobalSize(p);

и

GlobalFree(p);

 

Перемещаемая память

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

Итак, при работе программ, которые постоянно выделяют, расширяют, освобождают память, может возникнуть потенциальная проблема фрагментации виртуальной памяти. Для решения этой проблемы можно использовать перемещаемую память.

Блок перемещаемой памяти характеризуется тем, что его виртуальный адрес может в любое время измениться даже без физического перемещения блока памяти. Блок перемещаемой памяти можно выделить при помощи функция GlobalAlloc, передавая ей в качестве первого параметра GMEM_MOVEABLE или комбинированный флаг GHND, включающий в себя флаги GMEM_ MOVEABLE и GMEM_ZEROPOINT для обнуления блока памяти.

Флаг GMEM_MOVEABLE позволяет перемещать блок памяти в виртуальной памяти. Это не обязательно означает, что блок памяти будет перемещен в физической памяти, но адрес, которым пользуется программа для чтения и записи, может измениться.

Рассмотрим, как создается и используется блок перемещаемой памяти. Первым делом определяются указатель и переменная типа GLOBALHANDLE (описатель, селектор блока памяти):

 

#define N 256

. . .

int *p; GLOBALHANDLE hGlobal; // указатель и описатель (неинициализированные)

 

Затем выделяется память, например, так:

 

 hGlobal=GlobalAlloc(GHND, N*sizeof(int));

 

Перед тем, как обратиться к памяти, нужно зафиксировать блок с использованием вызова:

 

 p=(int *)GlobalLock(hGlobal);

 

Эта функция преобразует описатель памяти в указатель. Пока блок зафиксирован, Windows не изменяет его виртуальный адрес.

Доступ к i-тому элементу массива, хранящегося в блоке памяти, на который теперь ссылается p, осуществляется при помощи операции []:

 

. . . p[i] . . .

 

После работы с зафиксированным блоком с него необходимо снять фиксацию:

 

GlobalUnlock(hGlobal);

 

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

Когда нужно освободить память, следует вызвать функцию GlobalFree с параметром-описателем, а не с указателем (к этому времени с блока должна быть снята фиксация, если она производилась):

 

GlobalFree(hGlobal);

 

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

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

 Замечание. Для того чтобы получить описатель блока памяти, на который указывает указатель p, необходимо использовать функцию:

 

GLOBALHANDLE hGlobal=GlobalHandle(p);

 

Удаляемая память

Совместно с флагом GMEM_MOVEABLE при выделении памяти можно использовать опцию GMEM_DISCARDABLE. Блок памяти, выделенный с этим флагом, может быть удален из физической памяти ядром Windows, когда необходима свободная память.

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

Если память выделяется для неизменных данных, которые могут быть легко регенерированы (обычно загрузкой из файла), то можно сделать этот блок удаляемым. О том, что данные были сброшены, можно узнать, вызвав функцию GlobalLock и получив в ответ NULL. Теперь данные можно восстановить

Блок памяти не может быть удален до тех пор, пока счетчик фиксаций больше нуля. Для преднамеренного удаления блока памяти вызывается функция:

 

GlobalDiscard(hGlobal);

 

Отображаемые в память файлы

При работе с Win32 существует возможность читать и записывать данные в файл так, как будто это блок памяти. Этот прием часто рекомендуется использовать также при разделении памяти между двумя и более процессами.

Сначала создается обычный файл hFile с использованием функции CreateFile.а Если необходимо осуществить доступ к части файла, то вызывается функция MapViewOfFile. После этого можно использовать указатель, возвращаемый функцией, для доступа или модификации данных в файле, отображаемом в память.

 Замечание. Возникает вопрос, не излишне ли использовать дисковый файл, если необходимо лишь передать несколько байт между приложениями? В действительности нет необходимости явно открывать и использовать дисковый файл для получения отображения в памяти.  

Приложения могут передать специальное значение дескриптора равное 0хFFFFFFFF в функцию CreateFileMapping для получения отображения непосредственно в системный страничный файл. Это, по сути, создает блок разделяемой между приложениями памяти.

Другие функции работы памятью

Win32 также содержит следующие функции для работы с памятью:

FillMemory -заполнение конкретным байтом,

ZeroMemory - обнуление памяти, 

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

Для того чтобы проверить, возможен ли доступ по какому-либо указателю (т.е. действителен тот или иной указатель) есть ряд функций: IsBadCodePtr, IsBadReadPtr, IsBadWritePtr и IsBadStringPtr. Первая из этих функций просто принимает указатель в качестве параметра и возвращает ненулевое значение, если указатель действителен. Другие три функции получают указатель в качестве первого параметра и длину блока памяти в качестве второго параметра. Четвертая функция, кроме того, осуществляет проверку до тех, пока не встретит нулевой ограничитель строки


 

А также другие работы, которые могут Вас заинтересовать

8352. Китайские игры. Го в Древнем Китае 68 KB
  Го в Древнем Китае Содержание: 1. Введение. 2. Легенды о мудрых королях и гадания. 3. Го и война. 4. Го в классике. 5. Сумбур в Хань- и Вей-времена. 6. Литература. 1. ВВЕДЕНИЕ Китайской игре Вей-чи (Weichi,Weiqi), более известной у нас под ее...
8353. Main trends in the government’s policy on internationalization 71 KB
  Main trends in the governments policy on internationalization Internationalization of higher education is a reality. The Russian higher educational institutions have at their disposal much less funds than universities in the developed co...
8354. История древней Индии и Китая 37.5 KB
  Особый расцвет в индии наступает с 5-6 веков н.э, начинается процесс урбанизации. Ahimsa - не причинение вреда всему живого. Начинается развитие товарно-денежного обращения. Члены всех 4-ех варн отходили от своих традиционных занятий...
8355. Культура Древнего Востока. Бхавадгита 98 KB
  Культура Древнего Востока. БХАГАВАДГИТА КАК ОНА ЕСТЬ Арджуна спросил: О мой Господь, о Высшая личность, что такое Брахман? Что такое душа? Что такое кармическая деятельность? Что представляет собой это материальное проявление? Кто такие полубоги? По...
8356. История Китая. Краткий обзор 482.32 KB
  История Китая Китайская цивилизация - одна из старейших в мире. По утверждениям китайских учёных, её возраст может составлять пять тысяч лет, при этом имеющиеся письменные источники покрывают период не менее 3500 лет. Наличие систем администрат...
8357. Хрестоматія Китайської Літератури (від найдавніших часів до ІІІ ст. н.е.) 中国古代文学作品选 4.19 MB
  Хрестоматія Китайської Літератури(від найдавніших часів до ІІІ ст. н.е.) У хрестоматії широко представлена перекладна й оригінальна давньокитайська література, зокрема народна та авторська поезія, міфологічна, літописна, філософська ...
8358. Історія Китаю та китайських традицій 86.5 KB
  На сьогодні дві держави використовують назву Китай. Це Китайська Народна Республіка (КНР), яка контролює територію материкового Китаю, Гонконг та Макао, а також Республіка Китай, яка володіє островами Тайвань, Мацу і Кіньмень Китай (традиц...
8359. Влияние иностранных инвестиций на экономику Китая 124 KB
  Влияние иностранных инвестиций на экономику Китая Введение Процессы, происходящие в экономике Китая, на протяжении нескольких последних десятилетий привлекают к себе внимание специалистов и широкой мировой общественности. Достижения, демонстрируемые...
8360. История Китая 168.5 KB
  КИТАЙ По истории Китая вы помните, что в Китае сменялись разные династии. Для истории Китая характерна определенная цикличность. Приходит к власти новая династия, проводит реформы, все идет хорошо, процветание. А потом наступает упадок, и смена дина...