Подтвердить что ты не робот

Как sbrk/brk реализованы в Linux?

Я думал о том, как ядро ​​Linux реализует системные вызовы, и мне было интересно, может ли кто-нибудь дать мне представление высокого уровня о том, как работает sbrk/brk?

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

4b9b3361

Ответ 1

На очень высоком уровне ядро ​​Linux отслеживает память, видимую для процесса, как несколько "областей памяти" (struct vm_area_struct). Существует также структура, которая представляет (опять же на очень высоком уровне) процесс "всего адресного пространства" (struct mm_struct). Каждый процесс (кроме некоторых потоков ядра) имеет ровно один struct mm_struct, который, в свою очередь, указывает на все struct vm_area_struct для памяти, к которой он может обращаться.

Системный вызов sys_brk (найденный в mm/mmap.c) просто регулирует некоторые из этих областей памяти. (sbrk - обертка glibc вокруг brk). Это делается путем сравнения старого значения адреса brk (найденного внутри struct mm_struct) и запрошенного значения.

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

Ответ 2

вам нужно понять, как работает виртуальная память, и как отображение MMU относится к реальной ОЗУ.

реальная ОЗУ делится на страницы, традиционно 4kB каждый. каждый процесс имеет свое собственное MMU-отображение, которое представляет для этого процесса линейное пространство памяти (4 ГБ в 32-битном Linux). конечно, не все из них фактически распределены. во-первых, он почти пуст, то есть никакой реальной страницы не связано с большинством адресов.

когда процесс попадает на не выделенный адрес (либо пытается его прочитать, записать или выполнить), MMU генерирует ошибку (аналогично прерыванию), а система VM вызывается. Если он решает, что какая-то ОЗУ должна быть там, он выбирает неиспользуемую страницу RAM и связывается с этим диапазоном адресов.

Таким образом, ядру все равно, как этот процесс использует память, а процесс действительно не заботится о том, сколько оперативной памяти там, у него всегда будет такое же линейное 4 ГБ адресного пространства.

теперь brk/sbrk работают на несколько более высоком уровне: в принципе, любой адрес памяти "за пределами" этого знака недействителен и не будет получать страницу RAM, если будет получен доступ, вместо этого процесс будет убит. библиотека пользовательского пространства управляет выделениями памяти в этом пределе, и только при необходимости попросите ядро ​​увеличить ее.

Но даже если процесс начался с установки максимально допустимого значения brk, он не получал бы реальные страницы ОЗУ, пока он не начнет обращаться ко всем адресам памяти.

Ответ 3

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

Ответ 4

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

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