Как правильно посмотреть сколько оперативной памяти потребляет процесс
В этой заметке мы узнаем, какое значение памяти, используемой процессом, является верным.
Понимание использования памяти в Linux
Эта запись для тех людей, которые когда-либо задавались вопросом: «Почему простой текстовый редактор KDE занимает 25 мегабайт памяти?» Многие люди думают, что многие приложения Linux, особенно программы KDE или Gnome, «раздуты» исключительно на основании того, что сообщают такие инструменты, как ps. Хотя это может быть правдой, а может и нет, в зависимости от программы, в целом это не так — многие программы намного эффективнее с точки зрения памяти, чем кажется.
Что сообщает ps
Инструмент ps может выводить различную информацию о процессе, такую как его идентификатор процесса, текущее состояние выполнения и использование ресурсов. Двумя возможными выходами являются VSZ и RSS, которые обозначают «virtual set size» и «resident set size», которые обычно используются компьютерщиками по всему миру, чтобы увидеть, сколько памяти занимают процессы.
Например, вот результат

для программы Writer из офисного пакета LibreOffice на моем компьютере:
Размер памяти приводится в килобайтах. Согласно ps, Writer имеет виртуальный размер около 12 гигабайт (!) и резидентный размер около 500 мегабайт (оба числа выше указаны в килобайтах). При этом в офисном пакете открыт не очень большой файл, в котором я в данный момент пишу. Похоже, что большинству людей нравится случайным образом выбирать одно из этих числе и использовать его как реальное использование памяти процессом. Я не собираюсь сейчас объяснять разницу между VSZ и RSS, но, разумеется, это неправильный подход; ни одно из чисел не даёт точного представления о том, какова стоимость памяти для работы Writer.
Почему ps «неправильный»
В зависимости от того, как вы на это смотрите, ps не сообщает о реальном использовании памяти процессами. На самом деле он показывает, сколько реальной памяти занял бы каждый процесс, если бы он был единственным запущенным процессом. Конечно, на типичной Linux-машине в любой момент времени выполняется несколько десятков процессов, а это означает, что числа VSZ и RSS, сообщаемые ps, почти определённо «неправильны». Чтобы понять почему, необходимо узнать, как Linux обрабатывает разделяемые библиотеки в программах.
Большинство основных программ в Linux используют общие библиотеки для облегчения определённых функций. Например, программа редактирования текста поставляемых с окружением рабочего стола KDE будет использовать несколько общих библиотек KDE (для обеспечения взаимодействия с другими компонентами KDE), несколько X-библиотек (для отображения изображений, копирования и вставки) и несколько общих системных библиотек (для выполнения основных операций). Многие из этих разделяемых библиотек, особенно часто используемые, такие как libc, используются многими программами, работающими в системе Linux. Благодаря этому совместному использованию Linux может использовать отличный трюк: он загружает одну копию разделяемых библиотек в память и использует эту копию для каждой программы, которая на неё ссылается.
Хорошо это или плохо, но многие инструменты не особо заботятся об этом очень распространённом приёме; они просто сообщают, сколько памяти использует процесс, независимо от того, используется ли эта память совместно с другими процессами. Таким образом, две программы могут использовать большую разделяемую библиотеку, но при этом её размер учитывается в обоих общих показателях использования памяти; библиотека подсчитывается дважды, что может ввести в заблуждение, если вы не знаете, что происходит.
К сожалению, нелегко получить идеальное представление об использовании памяти процессом. Вам нужно не только понять, как на самом деле работает система, но и решить, как вы хотите решать некоторые сложные вопросы. Следует ли учитывать общую библиотеку, которая требуется только для одного процесса, в использовании памяти этим процессом? Если общая библиотека используется моими несколькими процессами, следует ли равномерно распределять её использование памяти между различными процессами или просто игнорировать? Здесь нет жёсткого правила; у вас могут быть разные ответы в зависимости от ситуации, с которой вы столкнулись. Легко понять, почему ps не старается изо всех сил сообщать «правильные» итоги использования памяти, учитывая неоднозначность.
Просмотр карты памяти процесса
Хватит разговоров; давайте посмотрим, как обстоят дела с этим «огромным» процессом Writer. Чтобы увидеть, как выглядит память Writer, воспользуемся программой pmap (с флагом -d после которого идёт PID (идентификатор процесса)):

Я вырезал много вывода; остальное похоже на то, что показано. Даже без полного вывода мы можем увидеть некоторые очень интересные вещи. Важно отметить, что в выводе каждая разделяемая библиотека указана дважды; один раз для сегмента кода и один раз для сегмента данных. Сегменты кода имеют режим «r-x—», в то время как данные установлены на «rw—». Столбцы Kbytes, Mode и Mapping — единственные, о которых мы будем заботиться, так как остальные не важны для обсуждения.
Если вы просмотрите вывод, вы обнаружите, что строки с наибольшим количеством килобайт обычно являются сегментами кода включённых разделяемых библиотек (те, которые начинаются с «lib», являются разделяемыми библиотеками). Что замечательно в этом, так это то, что они могут быть разделены между процессами. Если вы вычлените все части, которые совместно используются процессами, вы получите общее количество «writeable/private», которое отображается в нижней части вывода.
Это то, что можно считать дополнительными затратами этого процесса без учёта разделяемых библиотек. Следовательно, стоимость запуска этого экземпляра Writer (при условии, что все общие библиотеки уже загружены) составляет около 1 гигабайта. Это совсем другая история по сравнению с 12 гигабайтами, о которых сообщила ps.
Что все это значит?
Мораль этой истории заключается в том, что использование памяти процессами в Linux — сложный вопрос; вы не можете просто запустить ps и знать, что происходит. Это особенно верно, когда вы имеете дело с программами, которые создают множество идентичных дочерних процессов, например Apache. ps может сообщить, что каждый процесс Apache использует 10 мегабайт памяти, в то время как на самом деле предельная стоимость каждого процесса Apache составляет 1 мегабайт памяти. Эта информация становится критически важной при настройке параметра Apache MaxClients, который определяет, сколько одновременных запросов может обрабатывать ваш сервер.
Это также показывает, что стоит как можно больше придерживаться программного обеспечения для одного рабочего стола. Если вы запускаете KDE для своего рабочего стола, но в основном используете приложения Gnome, вы платите большую цену за множество избыточных (но разных) разделяемых библиотек. Придерживаясь только приложений KDE или Gnome, насколько это возможно, вы сокращаете общее использование памяти за счёт снижения предельных затрат памяти при запуске новых приложений KDE или Gnome, что позволяет Linux использовать больше памяти для других интересных вещей (например, файловый кэш, который значительно ускоряет доступ к файлам).
Так как тогда посчитать, сколько реально памяти занимает процесс в Linux?
С помощью ps или аналогичных инструментов вы получите только количество страниц памяти, выделенных этим процессом. Это правильный номер, но:
В выводе программ обращайте внимание на поля RSS и RES.
RES — используемая оперативная память, является подмножеством VIRT, представляет физическую память, не помещённую в раздел подкачки, которую в текущий момент использует задача.
RSS — это «resident set size» — физическая память без подкачки, которую использовала задача (в килобайтах). Псевдоним rssize, rsz.
Для просмотра фактически используемой памяти попробуйте команду pmap:
Будут выведены поля
Обратите внимание на нижнюю строку начинающуюся с «total kB», это поле RSS.

В команде top ищите поле RES — вы можете сделать сортировку по данному полю, как это показано на скриншоте ниже:

Виртуальная память в Linux не складывается?
Я смотрел системный монитор в Linux и заметил, что Firefox использует 441 МБ памяти, а несколько других приложений используют 274, 257, 232 и т. д. (Добавляя до 3 ГБ виртуальной памяти). Итак, я перехожу на вкладку «Ресурсы», и там говорится, что я использую 462 МБ памяти и не раздел подкачки не задействован. Я в замешательстве. Что означает объем виртуальной памяти, если программы на самом деле её не используют. Я подумал, может быть, память они запросили, но не используют, но как ОС узнает об этом? Я не могу придумать ни одной функции «при котором данным процессам может понадобиться такое огромное количество памяти в будущем».
Во-первых, разделяемая память не совсем правильно подсчитывается методом команды top. Во-вторых, да, программа запрашивает права на память, а затем использует её, но она может никогда не коснуться выделенной ей памяти, и ОС это знает. Нет проблем если между всеми приложениями будет поделена вся доступная память вместе с разделом подкачки, по крайней мере до тех пор, пока они не пытаются всё это использовать.
Память процесса Linux
Еще одним ресурсом, подлежащим распределению между процессами, является оперативная память. В Linux, как и во многих других современных операционных системах, для управления памятью используют механизм страничного отображения, реализуемого ядром операционной системы при помощи устройства управления памятью — W:[MMU]. При этом процессы работают с виртуальными адресами (virtual address) «воображаемой» памяти, отображаемыми устройством MMU на физические адреса (physical address) настоящей оперативной памяти.
Для отображения вся оперативная память (RAM) условно разбивается на «гранулы» — страничные кадры размером в 4 Кбайт, которые затем выделяются процессам. Таким образом, память процесса условно состоит из страниц (page), которым в специальных таблицах страниц (page table) сопоставлены выделенные страничные кадры (page frame).
При выполнении процесса преобразование его виртуальных адресов в физические выполняется устройством MMU «на лету» при помощи его. индивидуальной таблицы страниц.
Именно механизм страничного отображения позволяет эффективно распределять память между процессами путем размещения страниц процессов в произвольные свободные страничные кадры. Кроме этого, механизм страничного отображения позволяет выделять процессам память по требованию, добавляя дополнительные страницы и отображая их на свободные страничные кадры. Аналогично, ненужные процессу страницы могут быть удалены, а соответствующие страничные кадры высвобождены для использования другими процессами.
Виртуальная память
Помимо задачи распределения памяти между процессами, механизм страничного отображения используется ядром операционной системы и для решения задачи нехватки оперативной памяти. При определенных обстоятельствах имеющиеся в распоряжении свободные страничные кадры оперативной памяти могут быть исчерпаны. Одновременно с этим оказывается, что большую часть времени процессы используют лишь малую часть выделенной им памяти, а находясь в состоянии сна, не используют память вовсе.
Увеличить коэффициент полезного использования памяти позволяет еще одна простая идея — высвобождать страничные кадры при помощи выгрузки (page out) неиспользуемых страниц процессов во вторичную память (в специальную область «подкачки» SWAP, например, на диске), а при обращении к выгруженной странице — загружать (page in) ее обратно перед использованием.
За счет такого страничного обмена (paging или page swapping) организуется W:[виртуальная память], т. е. видимость большего количества (оперативной) памяти для размещения процессов, чем есть на самом деле.
В примере из листинга ниже в столбцах VSZ и RSS вывода команды ps показано потребление памяти процессами (в килобайтах). В столбце VSZ (virtual size) указывается суммарный объем всех страниц процесса (в том числе и выгруженных), а в столбце RSS (resident set size) — суммарный объем всех его страничных кадров в оперативной памяти, т. е. ее реальное потребление процессом.
Виртуальная и резидентная память процесса
$ ps fu
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
fitz 18690 0.0 0.0 10308 5432 pts/1 Ss 20:51 0:00 bash
fitz 19393 2.8 1.7 609744 143316 pts/1 Sl 21:27 0:11 \_ /usr/…/firefox
fitz 19526 0.0 0.0 6104 700 pts/1 R+ 21:33 0:00 \_ ps fu
Отображение файлов в память
Страничный обмен, помимо организации виртуальной памяти, имеет еще одно важнейшее применение. Именно на его основе реализуется незаменимый механизм отображения файлов в память процесса, доступный при помощи системных вызовов mmap/munmap (и дополнительных mlock, mprotect, msync, madvise и др.).
Для отображения файла в память процесса ему выделяют страницы в необходимом количестве, но не страничные кадры. Вместо этого, в таблице страниц формируются такие записи, как будто эти страницы уже были выгружены ранее в отображаемый файл.
При последующем обращении (on demand) процесса к какой-либо странице отображенной памяти, под нее выделяют страничный кадр и заполняют (read) соответствующим содержимым файла. Любые последующие изменения, сделанные процессом в отображенных страницах, сохраняются обратно (write back) в файл, если отображение выполнено «разделяемым» (shared) способом. Для страниц, отображенных «частным» (private) способом, используется принцип COW (copy-on-write), согласно которому любые попытки их изменения (write) приводят к созданию их копий (сору), куда и попадают изменения.
Таким образом, страницы отображенного файла, которые никогда не были востребованы процессом, не будут вовсе занимать оперативной памяти. Это обстоятельство широко используется для «загрузки» в процесс его программы и библиотек. В листинге ниже при помощи команды pmap показана карта (отображения файлов) памяти процесса командного интерпретатора bash.
Карта памяти процесса
$ ps fu
PID TTY STAT TIME COMMAND
26958 pts/0 Ss 0:00 bash
28540 pts/0 R+ 0:00 \_ ps f
[email protected]:
$ which bash
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0X000000 0X08048000 0x08048000 0xdb0c8 0xdb0c8 R E 0x1000
LOAD 0x0dbf04 0x08124f04 0x08124f04 0x04870 0x09820 RW 0x1000
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
GNU_RELRO 0x0dbf04 0x08124f04 0x08124f04 0x000fc 0x000fc R 0 0x1
[email protected]:
26958: bash
Address Kbytes Mode Offset Device Mapping
08048000 880 r-x— 0000000000000000 0fc:00000 bash
08124000 4 r—- 00000000000db000 0fc:00000 bash
08125000 20 rw— 00000000000dc000 0fc:00000 bash
0812a000 20 rw— 0000000000000000 000:00000 [ anon ]
086b9000 3676 rw— 0000000000000000 000:00000 [ anon ]
b753be000 1676 r-x— 0000000000000000 0fc:00000 libc-2.15.so
b76de000 8 r—- 00000000001a3000 0fc:00000 libc-2.15.so
b76e0000 4 rw— 00000000001a5000 0fc:00000 libc-2.15.so
b76e1000 16 rw— 0000000000000000 000:00000 [ anon ]
bfe78000 132 rw— 0000000000000000 000:00000 [ stack ]
mapped: 10312K writeable/private: 3908K shared: 240K
В память процесса интерпретатора отображен исполняемый ELF-файл его программы и ELF-файлы всех библиотек, от которых она зависит. Отображение ELF-файлов выполняется частями — сегментами (при помощи readelf можно получить их список), в зависимости от их назначения. Так, например, сегмент программного кода отображен в страницы, доступные на чтение r и выполнение x, сегмент данных отображен в страницы, доступные на чтение r и запись w, и т. д.
Более того, выделение страниц памяти по требованию в процессе работы процесса реализуется при помощи «воображаемого» отображения некоторого несуществующего, «анонимного файла» [anon] на страничные кадры. Необходимо отметить, что механизм виртуальной памяти при освобождении неиспользуемых страниц выгружает в специальную область подкачки SWAP только «анонимные» страничные кадры и «анонимизированные», полученные копированием при изменении (согласно принципу COW).
Неанонимные измененные кадры выгружаются непосредственно в соответствующие им файлы, а неизмененные освобождаются вовсе без выгрузки, т. к. уже «заранее выгружены».
В примере из листинга ниже иллюстрируются два способа выделения памяти по требованию: явный — при помощи системного вызова mmap с аргументом MAP_ANONYMOUS, и неявный (Доставшийся в наследство от классической ОС UNIX) — при помощи системного вызова brk. Явный способ позволяет выделять новые сегменты памяти процесса, тогда как неявный способ изменяет размер предопределенного «сегмента данных» процесса, позволяя увеличивать и уменьшать его по желанию, перемещая так называемый «break» — адрес конца этого сегмента.
Системные вызовы mmap/munmap и brk— выделение и высвобождение памяти
$ ldd hostname
libnsl.so.1 => /lib/i386-linux /llb/i386-linux-gnu/libc.so.6 (0xb7526000)
/lib/ld-linux. so.2 (0xb770a000)
$ strace hostname
execve(«/bin/hostname», [«hostname»], [/* 43 vans */]) = 0
open(«/etc/ld.so.cache», O_RDONLY|O_CLOEXEC) = 3
mmap2(NULL, 122191, PROT_READ, MAP_PRIVATE, 3, 0) = 0bdo76f000
open(«/lib/1386-linux 6, base_addr:0xb752b6c0, limit: 1048575, seg_32bit:1, contents: 0, read_exec_only: 0, limit_in_pages: 1, seg_not_present: 0, useable: 1>) = 0
mprotect(oxb76d0000, 8192, PROT_READ) = 0
mprotect(0xb76eo000, 4096, PROT_READ) = 0
mprobect(0x804b000, 4096, PROT_READ) = 0
mprotect(0xb7731000, 4096, PROT_READ) = 0
munmap(0xb76f0000, 122101) = = 0 ↑ /lib/ld-linux.so.2
brk(0) = 0x9e62000 ↓ /bin/hostname
Трасса команды hostname, показанная в листинге выше, поясняет работу загрузчика и компоновщика, (loader, ld) динамических библиотек ld-linux.
Системный вызов exec отображает для запуска в память процесса не только заданный ELF-файл /bin/hostname, но и (указанный в этом ELF-файле) загрузчик библиотек /lib/ld-linux.so.2, которому и передается управление до самой программы.
Загруженные библиотеки присоединяются (линкуются или же компонуются, linking), к программе /bin/hostname, после чего страницам их отображенных сегментов назначается ©Ф соответствующий режим доступа системным вызовом mprotect. По завершении компоновки отображение конифгурационного файла /etc/ld.so.cache снимается при помощи munmap, а управление передается исходной программе.
Потребление памяти
Суммарное распределение страниц памяти по сегментам процесса можно получить при помощи третьего набора столбцов (активировав его клавишами № команды top, как показано в листинге ниже. В столбце VIRT изображается суммарный объем (в килобайтах) всех страниц процесса, а в столбце RES — объем резидентных «страниц (находящихся в страничных кадрах оперативной памяти). В столбце SWAP указывается объем всех страниц, находящихся во вторичной памяти — как «анонимных» страниц, выгруженных в специальную область подкачки, так и «файловых» страниц, возможно, никогда не загружавшихся в оперативную память.
Столбцы CODE и DATA показывают объемы (в килобайтах) памяти,, выделенной, под сегменты кода и данных, а столбец SHR — объем резидентных страниц, которые используются (или могут быть использованы) совместно с другими процессами.
Распределение памяти по назначению
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
Cpu(s): 8.6%us, 2.4%sy, 0.0%ni, 88.6%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%si
Mem: 8192144k total, 7037720k used, 1154424k free, 238984k buffers
Swap: 4104188k total, 35376k used, 4068812k free, 4356372k cached
PID %МЕМ VIRT SWAP RES CODE DATA SHR nFLT nDRT S PR NI %CPU COMMAND
26958 0.1 10288 4936 5352 880 3852 1544 0 0 S 20 0 0 bash
Механизм отображения считывает содержимое файла в страничные кадры только один раз, вне зависимости от количества процессов, отображающих этот файл в свою память. В случае отображения одного файла разными процессами их страницы совместно отображаются на одни и те же страничные кадры, за исключением страниц, скопированных (согласно принципу COW) при изменении.
Такое поведение механизма отображения позволяет эффективно использовать оперативную память за счет использования разными программами одинаковых разделяемых библиотек. Так как ELF-файлы библиотек «загружаются* в память процессов при помощи отображения mmap, то в результате каждая библиотека размещается в оперативной памяти лишь единожды, вне зависимости от количества ее «использований».
Интегральная статистика по использованию виртуальной памяти может быть получена при помощи команды free, как показано в листинге ниже.
Статистика использования памяти
Строка Mem: содержит статистику использования оперативной памяти, а строка Swap: — статистику специальной области подкачки. В столбце total указан суммарный объем всех доступных страничных кадров, а в столбцах used и free — суммарные объемы использованных и свободных страничных кадров, соответственно.
В столбце cached указан объем страничного кэша (page cache), т. е. суммарный объем страничных кадров оперативной памяти, использованных под отображение файлов в память. Аналогично, в столбце buffers указывается объем буферного кэша, т. е. суммарный объем памяти, использованной ядром для кэширования «не-отображаемых» сущностей: метаданных файлов, дисковых блоков при прямом вводе-выводе на устройства и пр.
В листинге ниже показан пример потребления памяти процессом текстового редактора vi при попытке редактирования громадного файла в 1 Гбайт. Процесс загружает файл целиком, в результате чего он целиком оказывается в резидентных страницах сегмента данных процесса, что естественным образом увеличивает «чистый» расход оперативной памяти системы. После принудительного завершения процесса при помощи команды kill память естественным образом высвобождается.
Потребление памяти процессами
pts/0
$ dd if=/dev/urandom of=big bs=4069 count=262144
262144+0 записей получено
262144+0 записей отправлено
скопировано 1073741824 байта (1,1 GВ), 148,956 с, 7,2 МВ/с
-rw-r—r— 1 fitz fttz 1,0G дек. 3 12:26 big
$ vi big
pts/1
$ ps f
$ ps up 21685
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
fitz 21085 96.4 21.8 1826416 1786444 pts/0 Sl+ 21:14 0:18 vi big
total used free shared buffers cached
Mem: 8000 5687 2312 0 42 2709
-/+ buffers/cache: 2935 5065
Swap: 4007 0 4007
top — 21:14:43 up 3:56, 3 users, load average: 0.53, 0.40, 0.47
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
Cpu(s): 6.0%us, 5.89%sy, 0.2%ni, 83.7%id, 4.3%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 8192144k total, 5826856k used, 2365288k free, 43932k buffers
Swap: 4104188k total, 0k used, 4104188k free, 2777504k cached
PID %МЕМ VIRT SWAP RES CODE DATA SHR nFLT nDRT S PR NI %CPU COMMAND
21085 21.8 1783m 39m 1.7g 2148 1.7g 5676 0 0 S 20 0 0 vi
$ kill 21085
total used free shared buffers cached
Mem: 8000 3945 4054 0 42 2709
-/+ buffers/cache: 1193 6806
Swap: 4007 0 4007
LINUX|| Управление памятью в ОС Linux. Карта памяти
Управление физической памятью. Каждый процесс в системе linux на 32-разрядной машине получает 3 Гб виртуального адресного пространства для себя, а оставшийся 1 Гб памяти резервируется для его страничных таблиц и других данных ядра. 1 Гб ядра не виден в пользовательском режиме, но становится доступным в режиме ядра. Память ядра обычно находится в нижних физических адресах, но отображается в верхний гигабайт виртуального адресного пространства процесса. Адресное пространство создается с помощью вызова fork и перезаписывается при помощи системного вызова exec. Чтобы несоклько процессов могли совместно использовать физическую память linux отслеживает использование физической памяти, выделяет при необходимости дополнительную память пользовательским процессам и компонентам ядра, динамически отображает области физической памяти на адресное пространство различных процессов. В linux различают 3 зоны памяти:
1. ZONE_DMA – это страницы, которые можно использовать для операций DMA
2. ZONE_NORMAL – это нормальные отображаемые страницы
3.ZONE_HIGHMEM – Страницы с адресами в верхней области памяти, которые не имеют постоянного отображения. Точные границы и компоновка этих зон памяти зависит от архитектуры, например на платформах x86 некоторые устройства могут выполнять DMA операции только в 1-х 16 мегабайтах, следовательно зона DMA находится в диапазоне от 0 до 16 мегабайт. Ядро поддерживает структуру ZONE для каждой из этих 3-х зон и может выполнять выделение памяти для этих 3-х зон поотдельности. Основная память linux состоит из 3-х частей: 1-е две части – ядро и карта памяти (не вытесняются), остальная память разделена на страничные блоки, каждый из которых может содержать страницу текста, данных, стека, страницу с таблицей страниц или списки свободных страниц. Ядро поддерживает карту памяти, которая содержит всю информацию об использовании физической памяти системы.
Карта памяти организована следующим образом:
1. page desctiptor –описывает каждый физический страничный блок системы. Каждый дескриптор содержит указатель на адресное пространство, которому принадлежит страница, пару указателей, которые позволяют ему сформировать дважды связный список с другими дескрипторами (если страницы свободны) и прочие поля, размер дескриптора страницы равен 32 байтам.
2. zone descriptor – содержит информацию об использовании памяти в зоне, такую как количество активных и неактивных страниц нижний и верхний пределы для алгоритмов замещения страниц и др. Кроме того, дескриптор зоны содержит массив свободных областей. Первый элемент этого массива указывает на 1-й дескриптор страницы 1-го блока и свободных страниц.
Физическая память используется для различных целей, части которой могут выгружаться или не выгружаться на жесткий диск. Ядро системы, как и ни одна из его частей не выгружается на диск, остальная часть памяти доступна для страниц пользователей.
Кроме того операционная система linux поддерживает динамически загружаемые модули, в основном драйверы устройств. Они могут быть большего размера и каждому из них должен быть выделен непрерывный участок ядра памяти.
Виртуальный адрес страницы в linux состоит из 5 частей:
1. Глобальный каталог
В системе linux используется 4-х уровневая схема таблиц страниц. Поля каталогов используются как индекс в соответствующем каталоге страниц. Глобальный каталог указывает на верхний каталог, верхний каталог указывает на средний и средний указывает на конкретную страницу, которую необходимо использовать в данный момент времени.
Во-первых, скорости выделения памяти. Стандартная схема выделения памяти предусматривает сканирование списка неопределённой длины для нахождения свободной области памяти заданного размера, а это неприемлемо, так как в ОСРВ выделение памяти должно происходить за фиксированное время.
Во-вторых, память может стать фрагментированной в случае разделения свободных её участков уже запущенными процессами. Это может привести к остановке программы из-за её неспособности задействовать новый участок памяти. Алгоритм выделения памяти, постепенно увеличивающий фрагментированность памяти, может успешно работать на настольных системах, если те перезагружаются не реже одного раза в месяц, но является неприемлемым для встроенных систем, которые работают годами без перезагрузки.
Простой алгоритм с фиксированной длиной участков памяти очень хорошо работает в несложных встроенных системах.
Также этот алгоритм отлично функционирует и в настольных системах, особенно тогда, когда во время обработки участка памяти одним ядром следующий участок памяти обрабатывается другим ядром. Такие оптимизированные для настольных систем ОСРВ, как Unison Operating System или DSPnano RTOS, предоставляют указанную возможность.
Дата добавления: 2014-12-19 ; просмотров: 20 | Нарушение авторских прав
