
例如:
root@f42-vm:~# qemu-img create -f raw disk.raw 1G Formatting 'disk.raw', fmt=raw size=1073741824 root@f42-vm:~# root@f42-vm:~# ls -ls disk.raw 4 -rw-r--r-- 1 root root 1073741824 Oct 14 11:01 disk.raw root@f42-vm:~# root@f42-vm:~# qemu-img info --output=json disk.raw | jq { "children": [ { "name": "file", "info": { "children": [], "virtual-size": 1073741824, "filename": "disk.raw", "format": "file", "actual-size": 4096, "format-specific": { "type": "file", "data": {} }, "dirty-flag": false } } ], "virtual-size": 1073741824, "filename": "disk.raw", "format": "raw", "actual-size": 4096, "dirty-flag": false } root@f42-vm:~# 我觉得既然创建的磁盘文件是稀疏文件,那应该可以不用 0 填充前 4KB ,找了半天没找到原因,希望有兴趣的 v 友能一起研究一下。
找到原因了,就是这一行导致的:
https://github.com/qemu/qemu/blob/3bf5c57a11827d9fa706524d57ee3e5af68a429e/block/file-posix.c#L2476
根据 allocate_first_block 的注释的解释就是为了兼容xfs上的一个特殊的用例.
顺便记录一下怎么找到这行的:
strace -f -o strace.log qemu-img create -f raw disk.raw 1G 在 strace.log 里找到:
211983 pwrite64(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096, 0) = 4096 然后在gdb里打断点:
catch syscall pwrite64 # 也可以用 b pwrite64
然后就可以定位到是 allocate_first_block 调用的 pwrite64.
昨天懒得自己调试,想要靠问chatgpt找到答案,结果被chatgpt给整晕了,浪费了半天去验证chatgpt的各种猜测.
1 wniming OP 在 macos 上也是一样的行为,只不过在 macos 上是向前 16KB 写了 0 |
2 wniming OP 不管是在 linux 还是在 macos 上,直接用 truncate -s 1G disk.raw 分配磁盘文件也是能达到同样的效果,还不需要在文件开头写 0 。 |
3 busier 59 天前 via iPhone 反正 4K 和 4K 以下 都是至少要占用一个簇(通常默认 4K) ,弄小了也不能节省空间 纠结这干啥 |
4 ysc3839 59 天前 via Android raw 是直接使用系统的稀疏文件吧?那个 actual-size 应该是系统报告的。 |
5 BenHunDun 59 天前 我在 Ubuntu 24 下执行对应的命令 ``` ben@BenPC:/home/tmp/lfs/img$ qemu-img create -f raw disk.raw 1G Formatting 'disk.raw', fmt=raw size=1073741824 ben@BenPC:/home/tmp/lfs/img$ qemu-img info --output=json disk.raw | jq { "virtual-size": 1073741824, "filename": "disk.raw", "format": "raw", "actual-size": 0, "dirty-flag": false } ``` 创建 10M 大小的也是, 但没有挂载过这个 raw |
6 BenHunDun 59 天前 补充: 版本 qemu-system-x86_64 --version QEMU emulator version 8.2.2 (Debian 1:8.2.2+ds-0ubuntu1.10) Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers |
7 loading 59 天前 via Android 因为真实的磁盘的前 4kb 是 boot sector ,mbr ,pbr 等信息,不是直接就放文件? |
8 iseki 59 天前 via Android 我猜是某种兼容,因为很多系统上对 0 长度文件做内存映射会报错 |
9 kokutou 59 天前 via Android 防止装系统的时候解析磁盘分区表出问题,全 0 就被当作新硬盘。 可能以前不填 0 的时候,里面会有随机数据? |
10 eb0c6551 59 天前 牛蛙, 谢谢楼主分享调试过程 |
11 kiraskyler 58 天前 @loading 赞同,看过 ext4 内核代码,里面注释内容就是前面一点点空间给分区表 boot 之类的使用,ext4 前 1024 字节不使用 ref: https://www.kernel.org/doc/html/v4.19/filesystems/ext4/ondisk/index.html#layout 对于块组 0 的特殊情况,前 1024 个字节未使用,以允许安装 x86 引导扇区和其他奇怪的东西。 超级块将从偏移量 1024 字节开始,无论是哪个块(通常是 0 )。 但是,如果由于某种原因块大小 = 1024 ,则块 0 被标记为正在使用,并且超级块位于块 1 中。 |
12 iceecream 58 天前 对楼书的分析过程很感兴趣,能否分享一下相关资料? |