Память, доступная для программы сборки в Linux - PullRequest
2 голосов
/ 12 апреля 2020

Ради интереса я просто пытаюсь написать программу в сборке для Linux на ноутбуке с процессором x86, чтобы получить некоторую системную информацию. Поэтому я пытаюсь выяснить, сколько памяти доступно для моей программы и где, например, находится стек, и если и как я могу выделить дополнительную память, если это необходимо.

Долгое время go Я делал такие вещи на Atari ST, и была просто система 'mallo c', с которой я мог запросить память, и были функции для поиска доступной памяти.

Я знаю, Linux настроен по-другому, и у меня вроде есть целое адресное пространство, но я думаю, что есть области памяти, к которым я не могу прикоснуться.

И, похоже, стек по умолчанию настроен.

Я немного исследовал это, но не могу найти системный вызов 'ассемблер'. Большинство людей указывают на связывание C mallo c для управления памятью, но я не ищу менеджера памяти. Я просто хочу знать границы памяти моей программы.

Я нахожу такие вещи, как getrlimit, setrlimit, prlimit и brk и sbrk, но это, похоже, функции C, а не системные вызовы.

Чего мне не хватает?

1 Ответ

1 голос
/ 12 апреля 2020

Linux использует виртуальную память (и ASLR ). Atari ST тоже не использует, поэтому у него была фиксированная карта памяти для некоторых структур данных и кода ОС. (Поскольку ОС была в ПЗУ и не могла быть легко обновлена, некоторые люди даже задокументировали некоторые внутренние адреса.)

Linux пытается сохранить жесткую границу между ядром и пользовательским пространством, с определенный документированный API / ABI для пространства пользователя для взаимодействия с ядром через системные вызовы. (например, на x86-64, с помощью инструкции syscall). Пространству пользователя не нужно заботиться о том, что находится на другой стороне этой стены, и обычно даже не там, где его страницы находятся в виртуальной памяти, если на него есть указатели.

Когда glib c malloc хочет получить больше страниц из ОС, она использует mmap(MAP_ANONYMOUS) или brk для их получения и раздает их для небольших вызовов на malloc. Он хранит структуры данных бухгалтерского учета в пользовательском пространстве (разумеется, для каждого процесса).

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

Да, у каждого процесса есть свое собственное виртуальное адресное пространство. Вы можете касаться только выделенных вами частей, в противном случае возникшая ошибка страницы будет «недействительной» (ОС знает, что для этой виртуальной страницы не должно быть физической страницы) и доставит сигнал SIGSEGV вашему процессу, если вы попробуйте прочитать или написать это. («действительные» сбои страницы происходят из-за пространства подкачки или ленивого выделения / копирования при записи; ядро ​​обновляет таблицы страниц HW и возвращается в пространство пользователя, чтобы оно могло повторно выполнить неисправную инструкцию.)

Кроме того, ядро ​​требует большую половину виртуального адресного пространства для собственного использования. (https://wiki.osdev.org/Higher_Half_Kernel). См. Также https://www.kernel.org/doc/Documentation/x86/x86_64/mm.txt для макета карты памяти Linux x86-64.

Я не могу найти системный вызов 'Assembly'.

mmap и brk являются истинными системными вызовами. См. Раздел «Примечания» справочной страницы brk(2) . Справочные страницы раздела 2 - это системные вызовы, раздел 3 - функции lib c.

Конечно, в C, когда вы вызываете mmap(...), вы фактически вызываете функцию-обертку в glib c. glib c предоставляет функции-оболочки, а не встроенные макросы asm, которые напрямую используют инструкцию syscall.

См. также Полное руководство по Linux Системным вызовам который объясняет интерфейс asm, а также страницы VDSO. Linux отображает часть памяти ядра (только для чтения) в процесс пользовательского пространства, храня код и данные, чтобы getpid() и clock_gettime() могли работать в пользовательском пространстве.

Также различные вопросы и ответы по переполнению стека в том числе Каковы соглашения о вызовах для системных вызовов UNIX & Linux на i386 и x86-64


Так что я пытаюсь найдите, сколько памяти доступно моей программе

Системный вызов для запроса текущей карты памяти вашего процесса отсутствует. Парсинг /proc/self/maps будет вашим лучшим выбором.

См. Поиск отображенной памяти внутри процесса для некоторых забавных идей об использовании системных вызовов для сканирования диапазонов виртуального адресного пространства для отображаемых страниц. Например, как Linux mincore(2) syscall возвращает -ENOMEM, если указанный диапазон содержит не отображенные страницы.

...