使用 qemu-img 创建 raw 格式的磁盘文件,为什么前 4KB 要用 0 填充? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
wniming
V2EX    Linux

使用 qemu-img 创建 raw 格式的磁盘文件,为什么前 4KB 要用 0 填充?

  •  1
     
  •   wniming 59 天前 2722 次点击
    这是一个创建于 59 天前的主题,其中的信息可能已经有所发展或是发生改变。

    例如:

    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 友能一起研究一下。

    第 1 条附言    59 天前

    找到原因了,就是这一行导致的:

    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的各种猜测.

    12 条回复    2025-10-15 12:02:20 +08:00
    wniming
        1
    wniming  
    OP
       59 天前
    在 macos 上也是一样的行为,只不过在 macos 上是向前 16KB 写了 0
    wniming
        2
    wniming  
    OP
       59 天前
    不管是在 linux 还是在 macos 上,直接用

    truncate -s 1G disk.raw

    分配磁盘文件也是能达到同样的效果,还不需要在文件开头写 0 。
    busier
        3
    busier  
       59 天前 via iPhone
    反正 4K 和 4K 以下 都是至少要占用一个簇(通常默认 4K) ,弄小了也不能节省空间 纠结这干啥
    ysc3839
        4
    ysc3839  
       59 天前 via Android
    raw 是直接使用系统的稀疏文件吧?那个 actual-size 应该是系统报告的。
    BenHunDun
        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
    BenHunDun
        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
    loading
        7
    loading  
       59 天前 via Android
    因为真实的磁盘的前 4kb 是 boot sector ,mbr ,pbr 等信息,不是直接就放文件?
    iseki
        8
    iseki  
       59 天前 via Android
    我猜是某种兼容,因为很多系统上对 0 长度文件做内存映射会报错
    kokutou
        9
    kokutou  
       59 天前 via Android
    防止装系统的时候解析磁盘分区表出问题,全 0 就被当作新硬盘。
    可能以前不填 0 的时候,里面会有随机数据?
    eb0c6551
        10
    eb0c6551  
       59 天前
    牛蛙, 谢谢楼主分享调试过程
    kiraskyler
        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 中。
    iceecream
        12
    iceecream  
       58 天前
    对楼书的分析过程很感兴趣,能否分享一下相关资料?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2724 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 02:46 PVG 10:46 LAX 18:46 JFK 21:46
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86