Можете ли вы объяснить мне, как статические данные распределяются (освобождаются) в пространстве виртуальной памяти процесса при загрузке (выгрузке) динамического модуля?
Эта часть проста: каждый ELF
файл имеет PT_LOAD
сегменты, которые вы можете увидеть на выходе из readelf -Wl foo.so
. При загрузке общего объекта каждый из этих сегментов составляет mmap
ed в адресное пространство и служит как «распределение» для любых статических данных в этом общем объекте.
Когда выгружается 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
.
Благодаря @EmployedRussian, я выкопал немного больше в таблице динамических символов, кажется, что глобальные символы экспортируются только в таблицу динамических символов, когда задано -rdynamic. Как правило, они не экспортируются, поэтому динамический модуль не может получить доступ к ним из исполняемого файла. Это верно? – DKWH
@DKWH Существует 3 способа (которые я знаю) для символа, который будет экспортироваться из a.out: (1) вы ссылаетесь на '-rdynamic' (или' -E' или '--export-dynamic') или (2) вы напрямую связываетесь с 'foo.so', который использует символ, или (3) вы экспортируете символ в скрипт версии компоновщика. –