(虽然英特尔的论坛是一个更自然的地方this question我在这里发布它希望有更多的活动,而不是英特尔完全没有 - 到目前为止)
我无法创建使用Intel Media SDK(Linux服务器)来操作h264视频的动态链接库,并注意到MFX库设计中存在问题。我理解它的方式,程序应该链接到静态库,如:
$ g++ .... -L/opt/intel/mediasdk/lib/lin_x64 -lmfx
但是,此libmfx.a
库似乎会将所有来电委托给dlopen
ed 动态库/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
创建为静态库时, no 会崩溃。使用断点和反汇编程序,我设法制作了以下回溯快照,其中#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
位于libmfxhw64.so
,但它们似乎点击 .so
的不同版本(由于重新安置,绝对地址无意义:
libmfx.a
由于静态和共享Intel库都暴露了相同的API函数,我可以直接链接到libmfxhw64.so
内核,但我认为绕过静态“调度程序”是没有保证的( ?)
有人可以解释英特尔在设计背后的想法吗?规范,为什么提供一个只委托给具有相同接口的-rw-r--r-- 1 root root 136 Apr 27 15:51 logfile-04-20150427-07-00.log.gz
-rw-r--r-- 1 root root 133 Apr 27 23:18 logfile-04-20150427-15-00.log.gz
-rw-r--r-- 1 root root 151 Apr 28 04:40 logfile-04-20150427-23-00.log.gz
-rw-r--r-- 1 root root 161 Apr 28 05:14 logfile-04-20150428-04-00.log.gz
-rw-r--r-- 1 root root 134 Apr 28 06:45 logfile-04-20150428-05-00.log.gz
-rw-r--r-- 1 root root 125 Apr 28 08:46 logfile-04-20150428-06-00.log.gz
-rw-r--r-- 1 root root 191 Apr 28 09:27 logfile-04-20150428-08-00.log.gz
-rw-r--r-- 1 root root 281 Apr 28 10:43 logfile-04-20150428-09-00.log.gz
的静态库?
此外,SEGV似乎是由<RollingFile name="userlogfileAppender"
fileName="${sys:catalina.home}/webapps/miscLogs/uData/logfile/logfile.log"
filePattern="${sys:catalina.home}/webapps/miscLogs/uData/logfile/logfile-${logfileId}-%d{yyyyMMdd-HH}-00.log.gz"
immediateFlush="true"
bufferedIO="false">
<PatternLayout>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
</RollingFile>
<logger additivity="false" name="userlogfileLogger" level="debug">
<AppenderRef ref="userlogfileAppender"/>
或public void potentialDisruptions(String building, String targetDay, int targetStart, int targetEnd){
UI.printf("\nClasses in %s on %s between %d and %d%n",
building, targetDay, targetStart, targetEnd);
UI.println("=================================");
boolean containsCourse = false;
try {
Scanner scan = new Scanner(new File("classdata.txt"));
while(scan.hasNext()){
String course = scan.next();
String type= scan.next();
String day = scan.next();
int startTime = scan.nextInt();
int endTime = scan.nextInt();
String room = scan.next();
if(room.contains(building)){
if(day.contains(targetDay)){
if(endTime >= targetStart){
if( startTime<= targetEnd){
UI.printf("%s%n", course);
containsCourse = true;
}
}
}
}
}
if(!containsCourse){
UI.println("error");
}
}
catch(IOException e){
UI.println("File reading failed");
}
UI.println("=========================");
}
中的静态/全局数据引起的。有没有办法在动态加载的静态/全局部分强制执行特定的执行顺序?调试这类问题的最佳方法是什么?
在Intel Haswell i7-4790 @ 3.6Ghz上使用Intel Media SDK R2(ubuntu 12)和Intel Media SDK 2015R3-R5(Centos 7,1.13 / 1.15)进行测试
如果您有可用的英特尔MSDK设置,请编译my example code以确认问题。
答案 0 :(得分:3)
在最近发布的调度程序源代码文件“readme-dispatcher-linux.pdf”的最后,有这样的:
使用Dispatcher库之间存在细微差别 可执行模块或来自共享对象。减轻符号冲突 它本身与Linux *上的SDK共享对象之间应用程序应该: 1)链接libdispatch_shared.a而不是libmfx.a 2)在任何SDK包含之前定义MFX_DISPATCHER_EXPOSED_PREFIX
我已经使用过它,它可以解决你描述的符号冲突问题。
如果您安装“Intel Media Server Studio Professional 2016”,则可以找到此文件。有一个免费的社区版。源文件和PDF将在/ opt / intel / mediasdk / opensource /
中找到答案 1 :(得分:0)
(好吧,因为似乎没有人渴望,我会做一件不雅观的事情,并回答我自己的问题)。
经过大量研究试图打破无意的循环链接后,我发现ld
选项--exclude-libs
提供了安慰。基本上,我正在寻找一种方法来强制删除任何libmfx.a
符号后,在创建DLL时使用它们来解析lib.o
中的依赖项。这可以通过像这样创建so
来实现:
g++ -shared -o lib-a.so lib.o -L/opt/intel/mediasdk/lib/lin_x64 -lmfx -Wl,--exclude-libs=libmfx
一旦这样创建了库,Bob就是你的叔叔:
g++ -o main-so-a main.o lib-a.so -ldl
(请注意,仍然需要libdl
,因为英特尔的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
处理,但由于他们的疏忽,在这种情况下需要对其进行改造。
我认为使用--version-script
映射文件可以完成相同的操作,但由于我们希望完全封装libmfx.a
,因此可能会更加脆弱。