Понимание Linux /proc/id/maps
Я пытаюсь понять использование памяти встроенным приложением Linux. /proc/pid/maps
Утилита / файл, кажется, хороший ресурс для просмотра деталей. К сожалению, я не понимаю все столбцы и записи.
Есть ли хороший ресурс / документация для proc/pid/maps
утилита / файл?
Что означают анонимные записи inode 0? Похоже, это одни из самых больших сегментов памяти.
5 ответов
Каждый ряд в /proc/$PID/maps
описывает область непрерывной виртуальной памяти в процессе или потоке. Каждая строка имеет следующие поля:
address perms offset dev inode pathname
08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm
- адрес - это начальный и конечный адрес региона в адресном пространстве процесса
- permissions - описывает, как можно получить доступ к страницам в регионе. Существует четыре различных разрешения: чтение, запись, выполнение и совместное использование. Если чтение / запись / выполнение отключены,
-
появится вместоr
/w
/x
, Если регион не является общим, он является частным, поэтомуp
появится вместоs
, Если процесс пытается получить доступ к памяти способом, который не разрешен, генерируется ошибка сегментации. Разрешения могут быть изменены с помощьюmprotect
системный вызов. - смещение - если область была отображена из файла (используя
mmap
), это смещение в файле, где начинается отображение. Если память не была отображена из файла, это просто 0. - устройство - если область была сопоставлена из файла, это основной и младший номер устройства (в шестнадцатеричном формате), в котором находится файл.
- inode - если регион был отображен из файла, это номер файла.
- pathname - если регион был отображен из файла, это имя файла. Это поле пустое для анонимных сопоставленных регионов. Есть также специальные регионы с такими именами, как
[heap]
,[stack]
, или же[vdso]
,[vdso]
обозначает виртуальный динамический общий объект. Он используется системными вызовами для переключения в режим ядра. Вот хорошая статья об этом.
Вы можете заметить много анонимных регионов. Они обычно создаются mmap
но не прикреплены ни к какому файлу. Они используются для множества разных вещей, таких как общая память или буферы, не выделенные в куче. Например, я думаю, что библиотека pthread использует анонимные сопоставленные области в качестве стеков для новых потоков.
proc(5)
mmap(2)
"Понимание ядра Linux" 9.3. Регионы памяти; 16,2. Отображение памяти
"Понимание диспетчера виртуальной памяти Linux" 4.4 Области памяти
Пожалуйста, проверьте: http://man7.org/linux/man-pages/man5/proc.5.html
address perms offset dev inode pathname
00400000-00452000 r-xp 00000000 08:02 173521 /usr/bin/dbus-daemon
Поле адреса - это адресное пространство в процессе, который занимает отображение.
Поле perms представляет собой набор разрешений:
r = read
w = write
x = execute
s = shared
p = private (copy on write)
Поле смещения - это смещение в файл / что угодно;
dev - устройство (мажор: минор);
inode - это inode на этом устройстве.0 указывает, что ни один inode не связан с областью памяти, как в случае с BSS (неинициализированные данные).
Поле pathname обычно будет файлом, который поддерживает отображение. Для файлов ELF вы можете легко координировать свои действия с полем смещения, просматривая поле "Смещение" в заголовках программы ELF (readelf -l).
В Linux 2.0 нет поля с указанием пути.
Отображение памяти используется не только для отображения файлов в память, но также является инструментом для запроса оперативной памяти у ядра. Это те записи inode 0 - ваш стек, куча, сегменты bss и многое другое
Хотя в вопросе конкретно упоминаются встроенные системы, в заголовке упоминаются толькоproc/<pid>/maps
, что также очень полезно для понимания «обычных» программ. В этом более широком контексте важно понимать, что память, выделенная пользователем, может оказаться либо в куче, либо в любом количестве анонимных сегментов памяти. Таким образом, большие блоки анонимной памяти, скорее всего, поступили из .
То, что называется «as», точнее, представляет собой непрерывную область между памятью, выделенной для статических переменных (называемой сегментом BSS ), и адресом, называемым «обрывом программы» (см. диаграмму ниже). Изначально эта область пуста и кучи нет. При вызове он может создать/расширить кучу, запросив ядро — черезsyscall— для перемещения остановки программы. Аналогично, можно сжать кучу, если все адреса, прилегающие к разрыву программы, больше не используются.
Однако перенос перерыва в программе — не единственный способ освободить для себя больше места. Он также может запросить ядро — черезsyscall— чтобы зарезервировать блок пространства где-то между стеком и кучей (см. диаграмму ниже). Память, выделенная таким образом, отображается как «анонимные записи индексного 0», упомянутые в вопросе.
Стоит немного остановиться на системном вызове. Существует четыре типа карт памяти, которые можно создавать, и каждый из них используется для совершенно разных целей. Во-первых, память может быть как привязана к содержимому определенного файла, так и нет. Последняя называется «анонимной» картой. Во-вторых, память может быть «частной» или «общей». Частный означает, что изменения, внесенные одним процессом, не будут видны другим; обычно это реализуется ленивым и эффективным способом, называемым « копированием при записи ». Общий означает, что каждый процесс получит доступ к одной и той же базовой физической памяти. Ниже приведены известные мне варианты использования каждого типа карты памяти:
- Частные файлы: исполняемые файлы, динамические библиотеки, эффективные копии больших структур данных.
- Частные анонимные карты: сегменты BSS для динамических библиотек, пространство стека для потоков.
- Общие файлы: совместное использование памяти между несвязанными процессами.
- Общие анонимные карты: совместное использование памяти между связанными процессами.
Возвращаясь к , вы можете выяснить, какой тип карты памяти описывает каждая строка, просматривая столбцы «pathname» и «perms». (Эти имена столбцов взяты из ). Для карт файлов столбец «Имя пути» будет содержать фактический путь к сопоставляемому файлу. Для анонимных карт столбец «Путь» будет пустым. Существуют также некоторые специальные имена путей, например[heap]
и[stack]
. Для частных и общих карт столбец «разрешения» будет содержатьp
илиs
флаг соответственно.
Текущие реализации использования для небольших выделений и для больших. Имеет смысл выделять небольшие объемы памяти в куче, поскольку очень часто можно найти необходимое пространство без необходимости выполнения дорогостоящего системного вызова (например, путем повторного использования ранее освобожденного пространства). Однако большие выделения рискуют никогда не быть возвращены в операционную систему. Представьте, что произойдет, если вы выделите в куче большое выделение, а затем несколько маленьких. Даже если после освобождения большого выделения памяти перерыв в программе не может быть перенесен назад до тех пор, пока не будут освобождены все мелкие выделения. В этом простом примере предполагается, что выделения памяти передаются в кучу по порядку, что является наивным подходом, но он иллюстрирует, как куча значительно затрудняет освобождение памяти обратно в операционную систему.
Вот соответствующий раздел изman malloc
:
Обычно malloc() выделяет память из кучи и корректирует размер кучи по мере необходимости, используя sbrk(2). При выделении блоков памяти размером более MMAP_THRESHOLD байтов реализация glibc malloc() выделяет память как частное анонимное сопоставление с использованием mmap(2). По умолчанию размер MMAP_THRESHOLD составляет 128 КБ, но его можно настроить с помощью mallopt(3). До Linux 4.7 на выделения, выполняемые с помощью mmap(2), ограничение ресурса RLIMIT_DATA не влияло; начиная с Linux 4.7, это ограничение также применяется к выделениям, выполняемым с помощью mmap(2).
Подводя итог, если ваша программа использует , то, скорее всего, он отвечает за многие большие анонимные сегменты, которые отображаются в виртуальную память и о которых сообщает/proc/<pid>/maps
.
Предостережение покупателя: практически все, что я здесь написал, я узнал только сегодня, так что относитесь к этому с недоверием. Тем не менее, вот ссылки на ресурсы, которые я нашел очень полезными для понимания всего этого:
- Отличное введение в виртуальную память
- документации ядраДокументация ядра для /proc/&lt;pid&gt;/maps
- Это ссылка на всю документацию
/proc
файловая система, и, к сожалению, я не думаю, что есть способ напрямую ссылаться на соответствующую часть. Но если вы ищете «/proc/PID/maps», вы сможете найти нужное место.
- Это ссылка на всю документацию
- Точное определение кучи
- Почему вызов не создает кучу?
- Достоинства
brk()
противmmap()
- Как
malloc()
иfree()
работа