(Хотя форум Intel является более естественным местом для этот вопрос Я публикую это здесь в надежде на большую активность, чем полное отсутствие Intel — пока)
Я не могу создать динамическую библиотеку ссылок, которая использует Intel Media SDK (сервер Linux) для управления видео h264, и заметил проблему в дизайне библиотеки MFX. Насколько я понимаю, программы должны ссылаться на статический библиотека, как:
$ g++ .... -L/opt/intel/mediasdk/lib/lin_x64 -lmfx
Тем не менее, это libmfx.a
библиотека, по-видимому, делегирует все вызовы dlopen
издание динамический библиотека /opt/intel/mediasdk/lib64/libmfxhw64.so
, Стоит отметить эту функцию имена (и подписи), предоставляемые статическими и динамическими библиотеками идентичный, что немного запутанно и опасно.
Хотя я не понимаю обоснования этого дизайна, это не должно быть проблемой само по себе, если бы не то, что некоторая статическая / глобальная инициализация из библиотеки вызывает хаос, когда (статический) libmfx.a
включен в общий объект Т.е .:
+------+ +-----------+
| main | <-- | mylib.so |
+------+ | | +---------------+
| libmfx.a | (dlopen) | libmfxhw64.so |
| <------------- |
|+---------+| |+-------------+|
||MFXInit()|| || MFXInit() ||
||... || || ... ||
|| || || ||
+===========+ +===============+
Приведенная выше библиотека может быть собрана следующим образом:
$ g++ -shared -o mylib.so my1.o my2.o -lmfx
А затем (динамически) связаны с main.o
вот так:
$ g++ -o main main.o mylib.so -ldl
(Обратите внимание, что дополнительный libdl
необходимо разрешить libmfx.a
в dlopen()
libmfxhw64.so
.)
К сожалению, по первому MFXInit()
вызов программы вызывает ошибку сегментации (адрес доступа 0x0000400). Обратный след GDB:
#0 0x0000000000000400 in ?? ()
#1 0x00007ffff61fb4cd in MFXInit () from /opt/intel/mediasdk/lib64/libmfxhw64-p.so.1.13
#2 0x00007ffff7bd3a1f in MFX_DISP_HANDLE::LoadSelectedDLL(char const*, eMfxImplType, int, int) () from ./lib-a.so
#3 0x00007ffff7bd12b1 in MFXInit () from ./lib-a.so
#4 0x00007ffff7bd09c8 in test_mfx () at lib.c:12
#5 0x0000000000400744 in main (argc=1, argv=0x7fffffffe0d8) at main.c:8
(Обратите внимание, что MFXInit()
на стеке #3
это тот, в libmfx.a
тогда как тот в #1
в libmfxhw64.so
.)
Обратите внимание, что есть нет падение, когда mylib
создается как статический библиотека. Используя точки останова и дизассемблер, мне удалось сделать следующий снимок обратной трассировки, где в обоих случаях #1
я сидела MFXInit+424
, но они, кажется, ударить разные версии MFXQueryVersion
(абсолютные адреса не имеют смысла в связи с переездом):
#0 0x00007ffff6411980 in MFXQueryVersion () from /opt/intel/mediasdk/lib64/libmfxhw64-p.so.1.13
#1 0x00007ffff640c4cd in MFXInit () from /opt/intel/mediasdk/lib64/libmfxhw64-p.so.1.13
#2 0x000000000040484f in MFX_DISP_HANDLE::LoadSelectedDLL(char const*, eMfxImplType, int, int) ()
#3 0x00000000004020e1 in MFXInit ()
#4 0x0000000000401800 in test_mfx () at lib.c:12
#5 0x0000000000401794 in main (argc=1, argv=0x7fffffffe0e8) at main.c:8
Поскольку и статические, и разделяемые библиотеки Intel предоставляют одни и те же функции API, я Можно ссылка прямо в libmfxhw64.so
напрямую, но я полагаю, что обход статического «диспетчера» без гарантии (?)
Может ли кто-нибудь объяснить идею Intel в отношении указанного дизайна? Spec., Зачем предоставлять статическую библиотеку, которая делегирует только .so
что имеет идентичный интерфейс?
Кроме того, кажется, что SEGV вызван статическими / глобальными данными в любом libmfx.a
или же libmfxhw64.so
, Есть ли способ навязать определенный порядок выполнения на динамически загружаемых статических / глобальных разделах? Каков наилучший подход к устранению подобных проблем?
Протестировано с Intel Media SDK R2 (ubuntu 12) и Intel Media SDK 2015R3-R5 (Centos 7, 1.13 / 1.15) на Intel Haswell i7-4790 при 3,6 ГГц
Если у вас есть работающая настройка Intel MSDK, скомпилируйте мой пример кода подтвердить проблему.
В самом конце файла «readme-dispatcher-linux.pdf» в последних выпусках исходного кода диспетчера находится следующее:
Существует небольшая разница между использованием библиотеки Dispatcher от
исполняемый модуль или из общего объекта. Чтобы смягчить конфликт символов
между собой и общим объектом SDK в Linux *, приложение должно:
1) ссылка на libdispatch_shared.a вместо libmfx.a
2) определить MFX_DISPATCHER_EXPOSED_PREFIX, прежде чем любой SDK включает
Я использовал это, и это работает для решения проблемы конфликта символов, которую вы описываете.
Вы можете найти этот файл, если установите «Intel Media Server Studio Professional 2016». Существует бесплатная версия сообщества. Исходные файлы и PDF-файл можно найти по адресу / opt / intel / mediasdk / opensource /
(Хорошо, так как никто не кажется нетерпеливым, я сделаю глупость и отправлю ответ на свой вопрос).
После значительных исследований, пытаясь разорвать непреднамеренную циклическую связь, я обнаружил, что ld
вариант --exclude-libs
обеспечивает утешение. По сути, я искал способ принудительного удаления любого libmfx.a
символы после их использования для разрешения зависимостей в lib.o
при создании DLL. Это может быть достигнуто путем создания so
как это:
g++ -shared -o lib-a.so lib.o -L/opt/intel/mediasdk/lib/lin_x64 -lmfx -Wl,--exclude-libs=libmfx
Как только библиотека будет создана, Боб, ты, дядя:
g++ -o main-so-a main.o lib-a.so -ldl
(Обратите внимание, что libdl
все еще нужен, потому что Intel MFX (теперь внутри lib-a.so
) до сих пор использует dlopen
открывать libmfxhw64.so
)
От ld
справочная страница:
--exclude-libs lib,lib,...
Specifies a list of archive libraries from which symbols should not be
automatically exported. The library names may be delimited by commas or
colons. Specifying "--exclude-libs ALL" excludes symbols in all archive
libraries from automatic export. This option is available only for the
i386 PE targeted port of the linker and for ELF targeted ports. For i386
PE, symbols explicitly listed in a .def file are still exported,
regardless of this option. For ELF targeted ports, symbols affected
by this option will be treated as hidden.
Таким образом, по сути, дело не в том, чтобы убедиться, что соответствующие символы ELF отмечены скрытый. Обычно это будет сделано через #pragma
Это разработчики библиотеки (например, Intel), но из-за их небрежности это должно быть модифицировано в этом случае.
Я полагаю, то же самое можно было бы сделать с --version-script
файл карты, но это, возможно, оказалось более хрупким, так как мы хотим полностью инкапсулировать libmfx.a
тем не мение.