Проблемы, связанные с количеством и характеристиками кода в исполняемом файле, загружаемом в память для каждого процесса

Когда ОС, такая как Windows, хочет запустить исполняемый файл, сначала она должна загрузить его в ОЗУ. Из-за того, что память не расходуется впустую, ее частичная загрузка в память кажется более интеллектуальной, чем загрузка ее целиком.

Итак, при таком условии, мои вопросы таковы:

  1. Что именно происходит, когда элементы управления прибывают к инструкции, такой как JMP, содержащей адрес вне диапазона загруженного кода? Другими словами, как ОС распознает, что она должна прекратить выполнение инструкции, чтобы избежать перехода на нерелевантный адрес, и как она вычисляет, на какой странице находится соответствующий адрес?

  2. Сколько страниц кода ОС копирует в ОЗУ перед переходом к точке входа программы? Я имею в виду, всегда ли ОС копирует фиксированный объем кода или фиксированное количество страниц в оперативную память обязательно или это может быть неопределенным?

  3. Если ОС принимает решение о том, сколько кода или сколько страниц следует загрузить в память, то какие условия учитываются до принятия такого решения?

Спасибо всем.

Тег assembly не подходит для этого вопроса. Вы можете использовать тег paging.

Hadi Brais 02.05.2018 20:06

Я так не думаю. Для того, чтобы быть достаточно опытным в программировании на ассемблере X86, важно иметь хорошее представление о структуре операционных систем, архитектуре системы и ее деталях, и наоборот.

Farshid 03.05.2018 09:02

Да, но вопрос вовсе не в программировании на ассемблере.

Hadi Brais 03.05.2018 19:01
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
72
2

Ответы 2

Загрузчик программ современной ОС в основном использует mmap, а не read.. https://en.wikipedia.org/wiki/Memory-mapped_file#Common_uses говорит:

Perhaps the most common use for a memory-mapped file is the process loader in most modern operating systems (including Microsoft Windows and Unix-like systems.)

Это создает частное сопоставление с файловой поддержкой. (https://en.wikipedia.org/wiki/Virtual_memory).

  1. ... In other words how does the OS recognize that it must stop executing the instruction to avoid jumping to a irrelevant address and how does it calculate which page the related address situated in?

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

Аппаратное обеспечение виртуальной памяти ЦП («MMU», хотя на самом деле это не отдельная вещь в современных ЦП) обрабатывает обнаружение загрузки / сохранения / выборки кода с несопоставленных адресов. (Несопоставлено в соответствии с фактическими таблицами страниц, которые может видеть HW. Когда процесс "логически" отображает некоторую память, но ОС ленивается в этом отношении, мы говорим, что память не "подключена" к таблицам страниц, поэтому Ошибка страницы перенесет его в память, если это еще не сделано, и подключит его к таблицам страниц, чтобы аппаратное обеспечение могло получить к нему доступ (после промаха TLB для запуска аппаратного обхода страниц).


Если есть какая-либо среда выполнения перемещение символов, также известное как исправления, для учета программы, загружаемой по базовому адресу, отличному от того, на который она была связана, если ей нужны какие-либо абсолютные адреса в памяти, они могут потребовать записи страниц кода или данных, предназначенных только для чтения, загрязнение страницы виртуальной памяти, чтобы она поддерживалась файлом подкачки, а не исполняемым файлом на диске. например если ваш источник C включает int *foo = &bar; в глобальном масштабе, или int &foo = bar;

  1. How many pages of code does the OS copy into RAM before jumping to the entry point of the program?

Загрузчик программы, вероятно, имеет некоторую эвристику, чтобы убедиться, что точка входа и, возможно, некоторые другие страницы отображаются перед первой попыткой. Помимо этого IDK, если есть какие-либо специальные эвристики в коде виртуальной памяти для исполняемых файлов / библиотек по сравнению с неисполняемыми сопоставлениями.

О, я не видел вашего ответа, когда отправлял свой. Надеюсь, это не сделает мой дубликат :)

Margaret Bloom 02.05.2018 17:52

@MargaretBloom: похоже, мы использовали разные подходы. Я не искал возможных повторяющихся вопросов; ты сделал? (С нашими ответами здесь, возможно, следует закрыть некоторые другие вопросы как дубликаты этого: P)

Peter Cordes 02.05.2018 18:12

re: эвристика загрузчика: Да, и Linux, и Windows используют механизмы предварительной выборки, чтобы уменьшить влияние аппаратных ошибок страниц на производительность.

Hadi Brais 02.05.2018 18:39

Да, существуют механизмы опережающего чтения для жестких ошибок (чтобы избежать большого количества операций ввода-вывода на малых дисках), а также есть отдельная оптимизация для устранения ошибок при программных сбоях страниц. Последнее помогает в общем случае, когда страницы существуют в кэше страниц, но не отображаются в текущий процесс: когда возникает ошибка страницы при доступе к данной странице, Linux проверяет, присутствуют ли уже «соседние» страницы в ОЗУ. , и в таком случае приведет к добавлению (добавлению в таблицы страниц) нескольких из этих страниц с одной и той же ошибкой. Значение по умолчанию для устранения неисправности - 16, и вы можете увидеть это простым способом в ...

BeeOnRope 03.05.2018 03:12

... любой процесс, который обращается к большой области отображения поля, которая уже кэширована: количество мягких ошибок будет 1/16 от количества страниц. Эта оптимизация делает менее нужными трюки вроде MAP_POPULATE.

BeeOnRope 03.05.2018 03:12

Процессор делит адресное пространство на наборы адресов, называемых страницы.
. На x86 размер стандартной страницы составляет 4 КиБ, но возможны и другие размеры (например, 1 ГБ, 2 МБ). Страницы являются непрерывными, поэтому первая страница находится от адреса 0x00000000 до адреса 0x00000fff, для каждого адреса есть уникальная страница, связанная с ним.

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

Я несколько упростил историю, не проводя различия между виртуальными адресами (те, которые на самом деле разбиты на страницы, т.е. они могут иметь атрибуты) и физическими адресами (реальные адреса для использования, виртуальный адрес может быть сопоставлен с другим физическим адресом).

Среди различных атрибутов есть:

  • Тот, который сообщает процессору, следует ли считать страницу незагруженной. По сути, это заставляет ЦП генерировать исключение, когда инструкция пытается получить доступ к странице (например, читать с нее, включая выполнение, или записывать на нее).
  • Разрешения Например, только для чтения, неисполняемый файл, супервизор и т. д.
  • Физический адрес
    Основное использование пейджинга - изоляция, это может быть выполнено путем отображения одного и того же виртуального адреса Икс на разные физические адреса Y1 и Y1 для процесса P1 и P2 соответственно.

Помните, что эти атрибуты относятся к странице, они применяются ко всему диапазону адресов на странице (например, они влияют на адреса 4 KiB для страницы 4 KiB).

Имея это в виду:

  1. Когда процесс создается, все его страницы помечаются как отсутствующие. Доступ к ним приведет к сбою ЦП. Когда ОС загружает программу, загружается минимальный набор страниц (например, ядро, его часть, общие библиотеки, часть программного кода и данные), которые помечаются как присутствующие. Когда программа обращается к незагруженной странице, ОС проверяет, был ли адрес назначен программой, и если да (это действительная ошибка страницы), она загружает страницу и возобновляет выполнение. Если адрес не был назначен, возникает ошибка неверной страницы, и исключение сообщается самой программе.

  2. Я не знаю точного количества загруженных страниц, это можно было проверить разными способами, в том числе взглянув на ядро ​​Linux (для случая Linux) .
    Я не делаю этого, потому что фактическая используемая стратегия может быть сложной, и я не считаю ее особенно актуальной: ОС может загрузить всю программу, если она достаточно мала и нагрузка на память невысока. Там могут быть настройки для выбора той или иной стратегии. В общем, разумно предположить, что оптимистично загружается только фиксированное количество страниц.

  3. Факторы, влияющие на решение, могут быть следующими: объем доступной памяти, приоритет загруженного процесса, политика системы, созданная системным администратором (для предотвращения ее раздувания), тип процесса (такая служба, как СУБД, может быть помечена как с интенсивным использованием памяти), ограничение программы (например, на машине NUMA процесс может быть помечен для использования преимущественно локальной памяти, тем самым имея доступ к меньшему объему памяти, чем общий доступный), эвристика, реализованная ОС (например, она знает, что последнее выполнение потребовало K страниц кода / данных в пределах M миллисекунд от начала) .
    Проще говоря, алгоритм, используемый для загрузки оптимального количества страниц, должен немного предсказывать будущее, поэтому принимаются обычные соображения для случая (т.е. предположения, упрощения, сбор данных и тому подобное).

Программные сбои страницы включают случай, когда код или данные были горячими в кэше страниц для сопоставлений с файловой поддержкой. Это не ограничивается анонимными сопоставлениями для таких вещей, как malloc.

Peter Cordes 02.05.2018 18:15

@BeeOnRope Вы правы, у меня создалось впечатление, что программный сбой страницы произошел, когда ОС требовалось загрузить выделенную, но отсутствующую страницу. Спасибо :)

Margaret Bloom 03.05.2018 11:20

Другие вопросы по теме