编译静态的文件系统测试工具就可以在QEMU环境中测试自己的文件系统而不必担心机器崩溃啦,关于如何搭建内核开发环境可参考博主的前置文章:用VSCode + QEMU跑起来能够可视化Debug的NOVA文件系统。
今天介绍的是FIO文件系统测试法宝的静态编译
将下面命令中的path
替换为你想要的安装路径,用于找寻编译出来的二进制文件。例如,我将其设为我的home/fio-static
目录:/home/fio-static
git clone https://github.com/axboe/fio.git && cd fio
./configure --build-static --prefix=path
make && make install
运行完上述命令,安装就成功了。生成的二进制文件位于path/bin
,对博主来说就是:/home/fio-static/bin
,运行下述命令,验证是否安装成功
path/bin/fio -verison
如果安装成功,则显示FIO的版本号。
最后,验证其为静态二进制文件:
ldd path/bin/fio
输出应该是类似该文件为非动态可执行文件之类的东西,OK,现在把FIO二进制文件移植到initramfs
中去即可。
博主在完成移植后,启动QEMU,运行FIO,报错如下:
[ 11.340497] traps: fio[1107] trap invalid opcode ip:401520 sp:7ffd92667930 error:0 in fio[400000+1ff000]
遇到这个问题后,重新配置FIO,加入取消优化的选项。
git clone https://github.com/axboe/fio.git && cd fio
./configure --build-static --disable-optimizations --prefix=path
make && make install
重新拷贝启动QEMU,运行FIO,即可。
参考[x86][linux]AVX512指令引起的进程crash。
首先将编译出来的二进制FIO给Dump出来,看看在哪条指令处崩溃了:
objdump -D /home/fio-static/bin/fio
观察opcode ip:401520
,即在401520
指令处崩溃,定位:
0000000000401510 <prio_tree_init>:
401510: b8 01 00 00 00 mov $0x1,%eax
401515: b9 01 00 00 00 mov $0x1,%ecx
40151a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
401520: c4 e2 f9 f7 d1 shlx %rax,%rcx,%rdx
401525: 48 ff ca dec %rdx
401528: 48 89 14 c5 38 25 8e mov %rdx,0x8e2538(,%rax,8)
40152f: 00
401530: 48 ff c0 inc %rax
401533: 48 83 f8 40 cmp $0x40,%rax
401537: 75 e7 jne 401520 <prio_tree_init+0x10>
401539: 48 c7 05 f4 11 4e 00 movq $0xffffffffffffffff,0x4e11f4(%rip) # 8e2738
401540: ff ff ff ff
401544: c3 retq
401545: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40154c: 00 00 00
40154f: 90 nop
401520
处是shlx
指令,那么意味着执行指令shlx
崩溃了。这段代码应该对应什么呢?打开FIO源码仓库,利用VSCode全局搜索prio_tree_init
,找到如下代码:
static void fio_init prio_tree_init(void)
{
unsigned int i;
for (i = 0; i < FIO_ARRAY_SIZE(index_bits_to_maxindex) - 1; i++) {
index_bits_to_maxindex[i] = (1UL << (i + 1)) - 1;
}
index_bits_to_maxindex[FIO_ARRAY_SIZE(index_bits_to_maxindex) - 1] = ~0UL;
}
我这一看啊,就个汇编对应的肯定是移位操作。QEMU也是用的x86架构,不至于移位操作不支持吧,那肯定是GCC编译时一些优化选项在作怪,于是想到利用--disable-optimizations
移除FIO编译时的优化选项,再次观察objdump
的prio_tree_init
编译结果:
000000000040f4e1 <prio_tree_init>:
40f4e1: 55 push %rbp
40f4e2: 48 89 e5 mov %rsp,%rbp
40f4e5: 48 83 ec 10 sub $0x10,%rsp
40f4e9: be 40 00 00 00 mov $0x40,%esi
40f4ee: bf 08 ba 56 00 mov $0x56ba08,%edi
40f4f3: b8 00 00 00 00 mov $0x0,%eax
40f4f8: e8 43 d8 0a 00 callq 4bcd40 <_IO_printf>
40f4fd: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
40f504: eb 3a jmp 40f540 <prio_tree_init+0x5f>
40f506: 8b 45 fc mov -0x4(%rbp),%eax
40f509: 89 c6 mov %eax,%esi
40f50b: bf 2b ba 56 00 mov $0x56ba2b,%edi
40f510: b8 00 00 00 00 mov $0x0,%eax
40f515: e8 26 d8 0a 00 callq 4bcd40 <_IO_printf>
40f51a: 8b 45 fc mov -0x4(%rbp),%eax
40f51d: 83 c0 01 add $0x1,%eax
40f520: ba 01 00 00 00 mov $0x1,%edx
40f525: 89 c1 mov %eax,%ecx
40f527: 48 d3 e2 shl %cl,%rdx
40f52a: 48 89 d0 mov %rdx,%rax
40f52d: 48 8d 50 ff lea -0x1(%rax),%rdx
40f531: 8b 45 fc mov -0x4(%rbp),%eax
40f534: 48 89 14 c5 c0 09 8e mov %rdx,0x8e09c0(,%rax,8)
40f53b: 00
40f53c: 83 45 fc 01 addl $0x1,-0x4(%rbp)
40f540: 83 7d fc 3e cmpl $0x3e,-0x4(%rbp)
40f544: 76 c0 jbe 40f506 <prio_tree_init+0x25>
可以看到,shlx
已经不存在了,果然是编译器优化的问题。立马启动QEMU运行FIO,成功了。那么,从现在开始就可以在模拟环境中进行文件系统的FIO测试了。
OK,起飞