例如:
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 6 天前 via iPhone
反正 4K 和 4K 以下 都是至少要占用一个簇(通常默认 4K) ,弄小了也不能节省空间 纠结这干啥
|
![]() |
4
ysc3839 6 天前 via Android
raw 是直接使用系统的稀疏文件吧?那个 actual-size 应该是系统报告的。
|
![]() |
5
BenHunDun 6 天前
我在 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 6 天前
补充: 版本 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 6 天前 via Android
因为真实的磁盘的前 4kb 是 boot sector ,mbr ,pbr 等信息,不是直接就放文件?
|
8
iseki 6 天前 via Android
我猜是某种兼容,因为很多系统上对 0 长度文件做内存映射会报错
|
![]() |
9
kokutou 6 天前 via Android
防止装系统的时候解析磁盘分区表出问题,全 0 就被当作新硬盘。
可能以前不填 0 的时候,里面会有随机数据? |
![]() |
10
eb0c6551 6 天前
牛蛙, 谢谢楼主分享调试过程
|
11
kiraskyler 5 天前
@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 5 天前
对楼书的分析过程很感兴趣,能否分享一下相关资料?
|