Вопрос к гуру линкера там. Я работал с мекс-файлами в Matlab и получал огромное количество необъяснимых сбоев, поэтому я хочу копнуть немного глубже.
Можете ли вы объяснить мне, как статические данные распределяются (освобождаются) в пространстве виртуальной памяти процесса, когда динамический модуль загружается (выгружается)?
Я предполагаю, что это происходит в _init()
а также _fini()
функции. Однако назначается ли сегменту BSS кусок памяти в пространстве кучи наряду с другими динамическими распределениями памяти?
Как насчет глобальных данных в динамическом модуле? Будет ли возможность столкновения имен символов с основным исполняемым файлом?
Спасибо, что пролили свет на эти вопросы. Если мне нужно выбрать платформу, я бы хотел услышать мнение экспертов ELF, так как я делаю большую часть своей разработки для Linux.
Можете ли вы объяснить мне, как статические данные распределяются (освобождаются) в пространстве виртуальной памяти процесса, когда динамический модуль загружается (выгружается)?
Эта часть проста: каждый ELF
файл имеет PT_LOAD
сегменты, которые вы можете увидеть в выводе из readelf -Wl foo.so
, При загрузке общего объекта каждый из этих сегментов mmap
в адресное пространство, и это служит «распределением» для любых статических данных в этом общем объекте.
когда foo.so
выгружается, данные (и код) удаляются через munmap
системный вызов.
Я предполагаю, что это происходит в функциях _init () и _fini ()
Это предположение не правильно. _init
а также _fini
о динамический инициализация (например, глобальные переменные типа класса в C++
с нетривиальным конструктором / деструктором). Тем временем _init
вызывается, память для всех глобалов уже «зарезервирована» через mmap
,
Тем не менее, сегмент BSS
.bss
раздел включен в тот же PT_LOAD
сегмент, в котором находятся другие инициализированные (доступные для записи) данные. Вот почему существует отдельный p_filesz
а также p_memsz
в ElfXX_Phdr
: p_filesz
«покрывает» инициализированные данные и (больше) p_memsz
вызывает mmap
«выделить» пространство как для инициализированных, так и для .bss
данные.
Как насчет глобальных данных в динамическом модуле?
Что насчет этого? Я покрыл инициализированные данные выше.
Будет ли возможность столкновения имен символов с основным исполняемым файлом?
Конечно. Вы можете определить int foo = 42;
в a.out
, а также int foo = 24;
в foo.so
, Обычное правило таково, что если foo
виден в таблице динамических символов a.out
тогда foo
будет использоваться независимо от того, откуда на него ссылаются.
Осложнения возникают, когда a.out
не экспортирует foo
(если это не связано с -rdymamic
а также не ссылается на foo.so
) или когда foo.so
связан с -Bsymbolic
,
Других решений пока нет …