Linux Kernel-based Virtual Machine (KVM)是一款Linux开放源码虚拟化软件,基于硬件虚拟化扩展(Intel VT-X和AMD-V)和QEMU的修改版。kvm借用了QEMU一些组件,是一套虚拟系统,包括内核虚拟构架和处理器相关模块。本文尝试在Linux ubuntu 2.6.32-30-server环境里搭建KVM实现ALSA-1.0.25
Lib的调试,利用aplay程序来跟踪学习ALSA。
(1) KVM的搭建环境及ALSA库编译环境
swq@ubuntu:~/code/ldd_study/ldd3-env/alsa-1.0.25/alsa-lib-1.0.25$ uname -a
Linux ubuntu 2.6.32-30-server #59-Ubuntu SMP Tue Mar 1 22:46:09 UTC 2011 x86_64 GNU/Linux
(2) kvm启动脚本
swq@ubuntu:~/code/ldd_study/ldd3-env$ cat startos.sh
#!/bin/sh
kernel="/home/swq/code/ldd_study/ldd3-env/linux-2.6.28/arch/x86/boot/bzImage"
cmdline="console=ttyS0 root=/dev/hda rw"
kvm -m 128M -kernel ${kernel} -append "${cmdline}" \
-hda 200M.img \
-serial stdio \
-nographic -nodefaults \
-soundhw ac97 \
(3)编译ALSA-Lib-1.0.25和ALSA-Utils-1.0.25
a) 编译ALSA-Lib-1.0.25的命令:
swq@ubuntu:~/code/ldd_study/ldd3-env/alsa-1.0.25/alsa-lib-1.0.25$ CC=gcc CFLAGS=-g ./configure --prefix=$PWD/../install --build=x86_64-unknown-linux
swq@ubuntu:~/code/ldd_study/ldd3-env/alsa-1.0.25/alsa-lib-1.0.25$ make -j 16
swq@ubuntu:~/code/ldd_study/ldd3-env/alsa-1.0.25/alsa-lib-1.0.25$ make installb) 编译ALSA-Utils-1.0.25的命令:
swq@ubuntu:~/code/ldd_study/ldd3-env/alsa-1.0.25/alsa-utils-1.0.25$ ./configure --prefix=$PWD/../install --with-alsa-prefix=$PWD/../install/lib/ --with-alsa-inc-prefix=$PWD/../install/include/ --disable-xmlto --disable-alsamixer
swq@ubuntu:~/code/ldd_study/ldd3-env/alsa-1.0.25/alsa-utils-1.0.25$ make -j 16
swq@ubuntu:~/code/ldd_study/ldd3-env/alsa-1.0.25/alsa-utils-1.0.25$ make install
注意:在用configure配置时,必须加入CFLAGS=-g选项,因为-g选项告诉GCC产生能被GDB使用的调试信息以便调试。这里有个插曲,开始编译的时根据configure配置文件的帮助信息可知,需要注意三个参数build、host和target,build指定了编译该程序使用的平台。host指定了编译好的程序能够运行的平台;target指定了编译好的程序所处理的目标平台(通常交叉编译用不到target,只有构建编译本身(如gcc)才指定),由于编译ALSA-Lib-1.0.25、ALSA-Utils-1.0.25及搭建KVM的环境是同一环境,所以可以在configure时不用指定build选项,但却粗心了,把编译配置如下:
swq@ubuntu:~/code/ldd_study/ldd3-env/alsa-1.0.25/alsa-lib-1.0.25$ CC=gcc CFLAGS=-g ./configure --prefix=$PWD/../install --build=x86 --enable-shared=yes
swq@ubuntu:~/code/ldd_study/ldd3-env/alsa-1.0.25/alsa-lib-1.0.25$ make -j 16
swq@ubuntu:~/code/ldd_study/ldd3-env/alsa-1.0.25/alsa-lib-1.0.25$ make install
可是编译完成后,进入install目录,显示如下:
swq@ubuntu:~/code/ldd_study/ldd3-env/alsa-1.0.25/alsa-lib-1.0.25$ ls ../install/lib/
alsa-lib libasound.a libasound.la pkgconfig虽然加上--enable-shared=yes选项可还是生成了静态库,why?百思不得其解啊!实在没办法,尝试编译的环境里去除了--build选项。其实这里也该发现问题了,由于Linux x86是指Linux for 8086/IBM X86(就认为是我们用的台式机就好了)的版本,而x86_64是AMD公司生产的64位架构的版本,而Intel64位架构通常称为IA64,这两者是不同的。果真得到了预期的结果如下:
swq@ubuntu:~/code/ldd_study/ldd3-env/alsa-1.0.25/alsa-lib-1.0.25$ ls ../install/lib/
alsa-lib libasound.la libasound.so libasound.so.2 libasound.so.2.0.0 pkgconfig后来利用了Beyond Compare软件,对比了前后两次的config.log文件可以发现如下差异:
由此可以猜出是由于--build选项写入有些问题,而configure会在程序里判断是否支持动态库的加载,测试不通过就默认改为静态的编译方式了。
(4)把编译好的alsa库文件生成的lib库及bin目录下的文件拷贝入200M.img中,并把gdb工具一起放入,由于上面alsa库编译安装的时候已经指定prefix=$PWD/../install,所以只需要在busybox里面相应的设置prefix指定的路径就可以了。由于busybox里面有没有gdb,需要把gdb的依赖库必须一并放入相应的位置。
swq@ubuntu:~$ ldd /usr/bin/gdb
linux-vdso.so.1 => (0x00007fffefbff000)
libreadline.so.6 => /lib/libreadline.so.6 (0x00007fb3b10df000)
libncurses.so.5 => /lib/libncurses.so.5 (0x00007fb3b0e9c000)
libz.so.1 => /lib/libz.so.1 (0x00007fb3b0c84000)
libm.so.6 => /lib/libm.so.6 (0x00007fb3b0a01000)
libpython2.6.so.1.0 => /usr/lib/libpython2.6.so.1.0 (0x00007fb3b0550000)
libexpat.so.1 => /lib/libexpat.so.1 (0x00007fb3b0326000)
libdl.so.2 => /lib/libdl.so.2 (0x00007fb3b0122000)
libc.so.6 => /lib/libc.so.6 (0x00007fb3afd9f000)
libssl.so.0.9.8 => /lib/libssl.so.0.9.8 (0x00007fb3afb4c000)
libcrypto.so.0.9.8 => /lib/libcrypto.so.0.9.8 (0x00007fb3af7bc000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00007fb3af59f000)
libutil.so.1 => /lib/libutil.so.1 (0x00007fb3af39b000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb3b133f000)
(5)把编译好的alsa库文件生成的lib库及bin目录下的文件拷贝入200M.img中,并把gdb工具一起放入,由于上面alsa库编译安装的时候已经指定prefix=$PWD/../install,所以只需要在busybox里面相应的设置prefix指定的路径就可以了。由于busybox里面有没有gdb,需要把gdb的依赖库必须一并放入相应的位置。
swq@ubuntu:~/code/ldd_study/ldd3-env$ . startos.sh
ldd3-env login: root
login[115]: root login on 'ttyS0'
# gdb aplay
(gdb) set width 200
(gdb) set listsize 20
(gdb) directory /root/alsa/utl-src/aplay:/root/alsa/lib-src/src/pcm/:/root/alsa/lib-src/include/
(gdb) set args /root/toy8k.wav
(gdb) b main
(gdb) r
(gdb) c
(gdb) b pcm_hw.c:_snd_pcm_hw_open
(gdb) c
(gdb) bt
#0 _snd_pcm_hw_open (pcmp=0x7fffffffdd70, name=0x0, root=0x6121c0, conf=0x63d7a0, stream=SND_PCM_STREAM_PLAYBACK, mode=1) at pcm_hw.c:1369
#1 0x00007ffff790ff51 in snd_pcm_open_conf (pcmp=0x7fffffffdd70, name=0x0, pcm_root=0x6121c0, pcm_conf=0x63d7a0, stream=SND_PCM_STREAM_PLAYBACK, mode=1) at pcm.c:2171
#2 0x00007ffff79105b4 in snd1_pcm_open_named_slave (pcmp=0x7fffffffdd70, name=0x0, root=0x6121c0, conf=0x63d7a0, stream=SND_PCM_STREAM_PLAYBACK, mode=1, parent_conf=0x0) at pcm.c:2337
#3 0x00007ffff7956190 in snd_pcm_open_slave (pcmp=0x7fffffffdd70, root=0x6121c0, conf=0x63d7a0, stream=SND_PCM_STREAM_PLAYBACK, mode=1, parent_conf=0x0) at pcm_local.h:864
#4 0x00007ffff7959744 in snd_pcm_dmix_open (pcmp=0x7fffffffe238, name=0x63bf10 "dmix:0", opts=0x7fffffffdec0, params=0x7fffffffde90, root=0x6121c0, sconf=0x63d7a0, stream=SND_PCM_STREAM_PLAYBACK,
mode=0) at pcm_dmix.c:1015
#5 0x00007ffff7959f8a in _snd_pcm_dmix_open (pcmp=0x7fffffffe238, name=0x63bf10 "dmix:0", root=0x6121c0, conf=0x63c0a0, stream=SND_PCM_STREAM_PLAYBACK, mode=0) at pcm_dmix.c:1319
#6 0x00007ffff790ff51 in snd_pcm_open_conf (pcmp=0x7fffffffe238, name=0x63bf10 "dmix:0", pcm_root=0x6121c0, pcm_conf=0x63c0a0, stream=SND_PCM_STREAM_PLAYBACK, mode=0) at pcm.c:2171
#7 0x00007ffff79101b8 in snd_pcm_open_noupdate (pcmp=0x7fffffffe238, root=0x6121c0, name=0x63bf10 "dmix:0", stream=SND_PCM_STREAM_PLAYBACK, mode=0, hop=1) at pcm.c:2225
#8 0x00007ffff791058b in snd1_pcm_open_named_slave (pcmp=0x7fffffffe238, name=0x0, root=0x6121c0, conf=0x63bec0, stream=SND_PCM_STREAM_PLAYBACK, mode=0, parent_conf=0x63bad0) at pcm.c:2335
#9 0x00007ffff7964d4b in snd_pcm_open_slave (pcmp=0x7fffffffe238, root=0x6121c0, conf=0x63bec0, stream=SND_PCM_STREAM_PLAYBACK, mode=0, parent_conf=0x63bad0) at pcm_local.h:864
#10 0x00007ffff7967ba8 in _snd_pcm_softvol_open (pcmp=0x7fffffffe500, name=0x0, root=0x6121c0, conf=0x63bad0, stream=SND_PCM_STREAM_PLAYBACK, mode=0) at pcm_softvol.c:1083
#11 0x00007ffff790ff51 in snd_pcm_open_conf (pcmp=0x7fffffffe500, name=0x0, pcm_root=0x6121c0, pcm_conf=0x63bad0, stream=SND_PCM_STREAM_PLAYBACK, mode=0) at pcm.c:2171
#12 0x00007ffff79105b4 in snd1_pcm_open_named_slave (pcmp=0x7fffffffe500, name=0x0, root=0x6121c0, conf=0x63bad0, stream=SND_PCM_STREAM_PLAYBACK, mode=0, parent_conf=0x613510) at pcm.c:2337
#13 0x00007ffff793b110 in snd_pcm_open_slave (pcmp=0x7fffffffe500, root=0x6121c0, conf=0x63bad0, stream=SND_PCM_STREAM_PLAYBACK, mode=0, parent_conf=0x613510) at pcm_local.h:864
#14 0x00007ffff793dd5e in _snd_pcm_plug_open (pcmp=0x611588, name=0x40e731 "default", root=0x6121c0, conf=0x613510, stream=SND_PCM_STREAM_PLAYBACK, mode=0) at pcm_plug.c:1311
#15 0x00007ffff790ff51 in snd_pcm_open_conf (pcmp=0x611588, name=0x40e731 "default", pcm_root=0x6121c0, pcm_conf=0x613510, stream=SND_PCM_STREAM_PLAYBACK, mode=0) at pcm.c:2171
#16 0x00007ffff79105b4 in snd1_pcm_open_named_slave (pcmp=0x611588, name=0x40e731 "default", root=0x6121c0, conf=0x613510, stream=SND_PCM_STREAM_PLAYBACK, mode=0, parent_conf=0x612bc0) at pcm.c:2337
#17 0x00007ffff7962bc1 in _snd_pcm_asym_open (pcmp=0x611588, name=0x40e731 "default", root=0x6121c0, conf=0x612bc0, stream=SND_PCM_STREAM_PLAYBACK, mode=0) at pcm_asym.c:112
#18 0x00007ffff790ff51 in snd_pcm_open_conf (pcmp=0x611588, name=0x40e731 "default", pcm_root=0x6121c0, pcm_conf=0x612bc0, stream=SND_PCM_STREAM_PLAYBACK, mode=0) at pcm.c:2171
#19 0x00007ffff79105b4 in snd1_pcm_open_named_slave (pcmp=0x611588, name=0x40e731 "default", root=0x6121c0, conf=0x612bc0, stream=SND_PCM_STREAM_PLAYBACK, mode=0, parent_conf=0x6134a0) at pcm.c:2337
#20 0x00007ffff79468a1 in _snd_pcm_empty_open (pcmp=0x611588, name=0x40e731 "default", root=0x6121c0, conf=0x6134a0, stream=SND_PCM_STREAM_PLAYBACK, mode=0) at pcm_empty.c:103
#21 0x00007ffff790ff51 in snd_pcm_open_conf (pcmp=0x611588, name=0x40e731 "default", pcm_root=0x6121c0, pcm_conf=0x6134a0, stream=SND_PCM_STREAM_PLAYBACK, mode=0) at pcm.c:2171
#22 0x00007ffff79101b8 in snd_pcm_open_noupdate (pcmp=0x611588, root=0x6121c0, name=0x40e731 "default", stream=SND_PCM_STREAM_PLAYBACK, mode=0, hop=0) at pcm.c:2225
#23 0x00007ffff7910254 in snd_pcm_open (pcmp=0x611588, name=0x40e731 "default", stream=SND_PCM_STREAM_PLAYBACK, mode=0) at pcm.c:2247
#24 0x000000000040534f in main (argc=2, argv=0x7fffffffed98) at aplay.c:680