Загрузка DLL и экономия ОЗУ[Решено]

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Загрузка DLL и экономия ОЗУ[Решено]

Сообщение Maxizar » 18.03.2012 13:16:55

Здравствуйте. Решил все же накатать маленькую статью про DLL, по просьбе админа, НО столкнулся с таким вопросом, как базовый адрес DLL.
Как известно DLL, дают два преимущества:
1. Разработка отдельным человеком, после чего этим (кодом) могут пользоваться другие. (разделение труда)
2. При использовании DLL мы экономим ОЗУ, ведь общий код загружается только один раз.

Мой опыт: Я разрабатываю драйвер для ядра (Linux) и пишу интерфейс по средствам so библиотеки. Другие люди пишут клиент-сервер, web-интерфейс, и другие приложения которые общаются с устройством через данную so библиотеку, которая как раз и работает напрямую с драйвером.
1. Получаем разделения труда. И так как все остальные приложения пользуются одной и той же библиотекой, экономим (должны вроде как) ОЗУ в размере = (размер dll (грубо))* (кол-во приложений использующих dll).

У каждой DLL есть так называемый базовый адрес, по которому она будет загружена в виртуальное адресное пространство приложения. Назовем его Dll_BaseAddr.

Если приложение загружает несколько dll, у которых базовые адреса одинаковые, то загрузчик, понимает, что вторую библиотеку нужно сместить, (сместить все адреса переменных и т.п.).

Вопрос:
каким образом достигается экономия ОЗУ, ведь разные приложения могут загружать одну и туже dll, в различной последовательности?
То что делаются копии переменных, для каждого процесса понятно, вопрос именно про область кода.

Или Dll изначально загружаются в отдельную область виртуального пространства ядра, после чего происходить проброс адресов в про-во приложения?

Именно хочется понять, как происходит экономия ОЗУ за счет того, что область кода присутствует в одном экземпляре (должна вроде как), и может ли она проходить с отрицательным эффектом?
Может ли быть такая ситуация, что код dll, будет загружен несколько раз?
Последний раз редактировалось Maxizar 18.03.2012 15:00:13, всего редактировалось 1 раз.
Maxizar
постоялец
 
Сообщения: 385
Зарегистрирован: 20.03.2010 19:48:14

Re: Загрузка DLL и экономия ОЗУ

Сообщение B4rr4cuda » 18.03.2012 13:54:59

Maxizar писал(а):каким образом достигается экономия ОЗУ, ведь разные приложения могут загружать одну и туже dll, в различной последовательности?

В память библиотека грузится при запросе от первого приложения, последующие, загружающие ту же библиотеку, получают хэндл уже загруженной. Техподробностей не знаю.
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Re: Загрузка DLL и экономия ОЗУ

Сообщение Maxizar » 18.03.2012 14:05:18

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

Да это везде написано, Мне этого мало :( хочется деталей.... Просто уж как не хочется пилить исходники загрузчика (ld.so) Linux-a а там глядишь этого будет мало, нужно будет смотреть исходники ядра, менеджера памяти .... :?
Исходников для Windows-а ясное дело нет, но я думаю теория будет одинаковая.
Maxizar
постоялец
 
Сообщения: 385
Зарегистрирован: 20.03.2010 19:48:14

Re: Загрузка DLL и экономия ОЗУ

Сообщение B4rr4cuda » 18.03.2012 14:35:33

Maxizar писал(а):Исходников для Windows-а ясное дело нет, но я думаю теория будет одинаковая.

Куски есть. Большая часть от 2000го и можно найти сорцы 2003го. Я думаю они неполные, но некоторые вещи посмотреть можно.
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Re: Загрузка DLL и экономия ОЗУ

Сообщение Sergei I. Gorelkin » 18.03.2012 14:38:25

Страница памяти может быть отображена в адресное пространство нескольких процессов по любому адресу, в винде до висты это один и тот же адрес в каждом процессе, если он занят к моменту загрузки .dll, значит оптимизация не удалась и грузится копия. В висте сделали рандомизацию адресного пространства, из-за которой, возможно, никакой оптимизации больше нет (а может и есть - но тогда, узнав базу DLL в одном процессе, мы знаем ее и во всех остальных).
В .so, в отличие от .dll, генерируется код, независимый от адреса, поэтому в *nix секции кода могут отображаться и по разным адресам для разных процессов.

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

p.s. Есть свободные исходники Wine/ReactOS.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1406
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Загрузка DLL и экономия ОЗУ

Сообщение Maxizar » 18.03.2012 14:59:10

Ага, теперь вроде ястно... значит если все DLL, имеют один и тот же базовый адрес - Это плохо (в Windows), так как при загрузке первой dll вроде все хорошо, а вот при загрузке второй, адрес занят, и делается копия :evil: А если учесть что длл много и так же много приложений, и загрузка проходит в разных вариантах, то мы получаем реальный бардак... Теперь ястно, почему системные dll в Windows имеют разные базовые адреса, отличные от стандартного.

В nix Все хорошо :).

Вывод:
- В Windows в большинстве случаев мы получаем только разделение труда, экономию ОЗУ ну как повезет.
- В nix получаем обе плюшки. Экономию ОЗУ за счет одной копии общего кода, и собтственно разделения труда.

PS. Сегодня моя любовь к nix увеличилась :)
Maxizar
постоялец
 
Сообщения: 385
Зарегистрирован: 20.03.2010 19:48:14

Re: Загрузка DLL и экономия ОЗУ[Решено]

Сообщение Sergei I. Gorelkin » 18.03.2012 15:40:59

Я, возможно, не совсем правильно выразился. Копия <> релокация, если есть к примеру две dll с одинаковым базовым адресом (пусть будет 1000) и два процесса, сценарий может быть таким:
1) процесс1 загружает длл 1 по адресу 1000.
2) процесс1 загружает длл2, адрес 1000 занят, грузится по другому адресу (пусть 2000)
3) процесс2 загружает первой длл2, загрузчику совершенно не обязательно грузить ее по адресу 1000. Он видит что длл2 уже имеется по адресу 2000 и может загрузить ее по тому же адресу в процесс2. Копия будет сделана только в случае если адрес 2000 в процессе2 занят.
4) процесс2 загружает длл1, она грузится по адресу 1000 (опять же без копии если этот адрес не занят).
В итоге все вполне нормально разделяется. Разные базовые адреса нужны только для ускорения загрузки большого числа dll, т.к. при загрузке dll по базовому адресу не требуется релокация.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1406
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Загрузка DLL и экономия ОЗУ[Решено]

Сообщение Maxizar » 18.03.2012 16:21:47

Ммм. Хорошо, тогда очень тонкий момент, который я не совсем понял:
3) процесс2 загружает первой длл2, загрузчику совершенно не обязательно грузить ее по адресу 1000. Он видит что длл2 уже имеется по адресу 2000 и может загрузить ее по тому же адресу в процесс2. Копия будет сделана только в случае если адрес 2000 в процессе2 занят.


В этот момент у нас будет две копии длл2 одна по аддресу 2000 другая по аддресу ну скажем 3000 (копия, которую пришлось сделать в процесс2, так как адрес 2000 был занят)
Тобишь у нас две копии длл2 в памяти с разным кол-вом ссылок. Если процесс3 захочет загрузить длл2, то он сможет это сделать по адресу 2000 либо по 3000, увеличив соответственно кол-во ссылок той или иной копии. Если же у процесса3 эти адреса будут заняты, то будет сделана третья копия в ОЗУ правильно?
Maxizar
постоялец
 
Сообщения: 385
Зарегистрирован: 20.03.2010 19:48:14

Re: Загрузка DLL и экономия ОЗУ[Решено]

Сообщение Sergei I. Gorelkin » 18.03.2012 17:19:40

:( проверка показывает, что такой сценарий не происходит, т.е. загрузчик не обращает внимание на другие процессы.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1406
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Загрузка DLL и экономия ОЗУ[Решено]

Сообщение Maxizar » 18.03.2012 18:25:59

Да нашел подтверждения вашим словам:

"Delphi 5 руководство разработчика" - Стив Тейксейрой Том 1 стр 356.
Установка базового адреса библиотеки dll
Код библиотеки ДЛЛ разделяется между процессами только в том случае, если эту библиотеку можно загрузить
в адресное пространство процессов всех заинтересованных клиентов по некоторому предпочтительному базовому
адресу библиотеки ДЛЛ. Если базовый адрес перекрывается или занят Загрузчик меняет этот адрес с учетом размера ДЛЛ
В этом случае ни один из перемещенных образов ДЛЛ не используется никакими другими процессами в системе
Т.е. каждый перемещенный экземпляр библиотеки ДЛЛ занимает блок собственной физической памяти.

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


Если кому-то нужны книги
Том 1, Том 2.

PS. Спасибо, что помогли разобраться.
Maxizar
постоялец
 
Сообщения: 385
Зарегистрирован: 20.03.2010 19:48:14


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4

Рейтинг@Mail.ru