V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
wniming
V2EX  ›  Linux

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

  •  1
     
  •   wniming · 6 天前 · 1764 次点击

    例如:

    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 条附言  ·  6 天前

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

    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
       6 天前
    在 macos 上也是一样的行为,只不过在 macos 上是向前 16KB 写了 0
    wniming
        2
    wniming  
    OP
       6 天前
    不管是在 linux 还是在 macos 上,直接用

    truncate -s 1G disk.raw

    分配磁盘文件也是能达到同样的效果,还不需要在文件开头写 0 。
    busier
        3
    busier  
       6 天前 via iPhone
    反正 4K 和 4K 以下 都是至少要占用一个簇(通常默认 4K) ,弄小了也不能节省空间 纠结这干啥
    ysc3839
        4
    ysc3839  
       6 天前 via Android
    raw 是直接使用系统的稀疏文件吧?那个 actual-size 应该是系统报告的。
    BenHunDun
        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
    BenHunDun
        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
    loading
        7
    loading  
       6 天前 via Android
    因为真实的磁盘的前 4kb 是 boot sector ,mbr ,pbr 等信息,不是直接就放文件?
    iseki
        8
    iseki  
       6 天前 via Android
    我猜是某种兼容,因为很多系统上对 0 长度文件做内存映射会报错
    kokutou
        9
    kokutou  
       6 天前 via Android
    防止装系统的时候解析磁盘分区表出问题,全 0 就被当作新硬盘。
    可能以前不填 0 的时候,里面会有随机数据?
    eb0c6551
        10
    eb0c6551  
       6 天前
    牛蛙, 谢谢楼主分享调试过程
    kiraskyler
        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 中。
    iceecream
        12
    iceecream  
       5 天前
    对楼书的分析过程很感兴趣,能否分享一下相关资料?
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   1257 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:47 · PVG 07:47 · LAX 16:47 · JFK 19:47
    ♥ Do have faith in what you're doing.