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

Дополнительная информация о макете памяти исполняемой программы (процесса)

Я присутствовал на интервью для samsung. Они задали много вопросов по макету памяти программы. Я ничего не знаю об этом.

Я просмотрел его "Макет памяти исполняемой программы". "Макет памяти процесса".

Я удивлен, увидев, что информации по этим темам мало. Большинство результатов - это вопросы форума. Мне просто интересно, почему?

Вот несколько ссылок, которые я нашел:

Я хочу изучить это из правильной книги, а не для некоторых ссылок в Интернете. (Рэнди Хайд - также книга, но другая книга). В какой книге я могу найти ясную и дополнительную информацию по этому вопросу?

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

Все это создание макета - это задача linker правильно? Где я могу больше узнать об этом процессе. Я хочу ПОЛНАЯ информация из программы на диске в ее исполнение на процессоре.

EDIT:

Вначале я был неясен даже после прочтения ответов, приведенных ниже. Недавно я просмотрел эти статьи после их прочтения, я ясно понял вещи.

Ресурсы, которые помогли мне понять:

Да, "макет исполняемой программы (PE/ELF)"!= "Макет памяти процесса" ). Выведите для себя 3-ю ссылку.:)

После очистки моих понятий мои вопросы заставляют меня выглядеть настолько глупо.:)

4b9b3361

Ответ 1

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

Чтобы ответить на ваши вопросы:

  • Книги:
    • Если вам интересно, как процессы выкладывают свою память, посмотрите Понимание ядра Linux. В главе 3 рассказывается о дескрипторах процессов, создании процессов и разрушающих процессах.
    • Единственная книга, которую я знаю о том, что касается связывания и загрузки в деталях, - это Linkers and Loaders от Джона Левина. Там онлайн и версия для печати, поэтому проверьте это.

  • Исполняемый код создается компилятором и компоновщиком, но это компоновщик, который помещает вещи в бинарный формат, который требуется ОС. В Linux этот формат обычно ELF, в Windows и старше Unixes COFF, а в Mac OS X - Mach-O. Однако это не фиксированный список. Некоторые ОС могут поддерживать несколько бинарных форматов и поддерживать их. Линкерам необходимо знать выходной формат для создания исполняемых файлов.

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

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

    Кроме того, макет памяти процесса содержит некоторое пространство для stack и heap, где идут кадры процессов и динамически распределенная память. Они обычно живут на противоположных концах большого адресного пространства.

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

Ответ 2

Вот один из способов, которым программа может быть выполнена из файла (* nix).

  • Процесс создается (например, fork()). Это дает новому процессу собственную карту памяти. Это включает в себя стек в некоторой области памяти (обычно где-то в памяти).
  • Новый процесс вызывает exec(), чтобы заменить текущий исполняемый файл (часто оболочку) новым исполняемым файлом. Часто для отображения страницы запроса настраиваются новые исполняемые файлы .text(исполняемый код и константы) и .data(r/w инициализированные переменные), то есть они отображаются в пространство памяти процесса по мере необходимости. Часто сначала начинается раздел .text, за которым следует .data. Раздел .bss(неинициализированные переменные) часто выделяется после раздела .data. Много раз он сопоставляется для возврата страницы нулей, когда страница, содержащая переменную bss, сначала открывается. Куча часто начинается с границы следующей страницы после раздела .bss. Затем куча растет в памяти, когда стек растет (помните, что я обычно говорил, есть исключения!).

Если куча и стол сталкиваются, это часто вызывает ситуацию с отсутствием памяти, поэтому стек часто помещается в большую память.

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