В strace
выходных данных пути к библиотекам, которые вызывают исполняемые файлы, находятся в вызовах open()
. Это системный вызов, используемый исполняемыми файлами, которые динамически связаны? Как насчет dlopen()
? open()
не вызов, который я бы предположил, сыграл бы роль в исполнении программ.
23
ld-linux
отображается ядром как частьexecve
системного вызова.dlopen не имеет ничего общего с общими библиотеками, как вы о них думаете. Существует два способа загрузки общего объекта:
main
функции и настраивать пространство процесса приложения, чтобы приложение могло найти функции библиотеки. Это включаетopen()
в себя lubrary, а затемmmap()
его, а затем настроить некоторые таблицы поиска.libdl
, с которым хотите связать , из которого вы затем (используя первый метод) можете вызватьdlopen()
иdlsym()
функции. С помощью dlopen вы получаете дескриптор библиотеки, который затем можете использовать с dlsym, чтобы получить указатель на конкретную функцию. Этот метод гораздо сложнее для программиста, чем первый (поскольку вам нужно выполнить настройку вручную, а не компоновщик, чтобы сделать это автоматически), и он также более хрупок (так как вы не получаете компиляцию -time проверяет, что вы вызываете функции с правильными типами аргументов, как вы получаете в первом методе), но преимущество заключается в том, что вы можете решить, какой общий объект загружать во время выполнения (или даже загружать ли его вообще), делая Этот интерфейс предназначен для функциональности типа плагина. Наконец, интерфейс dlopen также менее переносим, чем другие, так как его механизм зависит от точной реализации динамического компоновщика (отсюда и libtoollibltdl
, который пытается абстрагироваться от этих различий).источник
Сегодня большинство операционных систем используют метод для разделяемых библиотек, представленный в конце 1987 года SunOS-4.0. Этот метод основан на отображении памяти через mmap ().
Учитывая тот факт, что в начале 1990-х годов Sun даже пожертвовала старый код на основе a.out (в то время Solaris был уже основан на ELF) людям, работающим с FreeBSD, и что этот код позже был передан многим другим системам (включая Linux). Вы можете понять, почему между платформами нет большой разницы.
источник
ltrace -S
Анализ минимального примера показывает, чтоmmap
используется в Glibc 2,23В glibc 2.23, Ubuntu 16.04, работающий
latrace -S
на минимальной программе, которая используетdlopen
:шоу:
поэтому мы сразу видим, что
dlopen
звонитopen
+mmap
.Удивительный
ltrace
инструмент отслеживает как библиотечные, так и системные вызовы, и поэтому идеально подходит для изучения того, что происходит в этом случае.Более внимательный анализ показывает, что
open
возвращается дескриптор файла3
(следующий свободный после stdin, out и err).read
затем использует этот файловый дескриптор, но аргументы TODO Whymmap
ограничены четырьмя, и мы не можем видеть, какой fd там использовался, поскольку это 5-й аргумент .strace
как и ожидалось, подтверждает, что3
это тот, и порядок вселенной восстановлен.Храбрые души также могут рисковать в glibc-коде, но я не смог найти его
mmap
после быстрого поиска, и я ленив.Протестировано на этом минимальном примере со сборкой шаблонов на GitHub .
источник
strace
отчеты о системных вызовах (т.е. функциях, реализованных непосредственно ядром). Динамические библиотеки не являются функцией ядра;dlopen
является частью библиотеки C, а не ядра. Реализацияdlopen
вызоветopen
(это системный вызов), чтобы открыть файл библиотеки, чтобы его можно было прочитать.источник
ltrace
.ltrace -S
идеально подходит для анализа этого, поскольку он также показывает системные вызовы