IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

从磁盘映像中挂载或提取指定分区

林健的BLOG 2009-11-17 23:27:23 累计浏览 3,791 次
本机暂存

      最近在做虚拟机相关的事,需要处理一些磁盘和分区的映像文件。如何从一个磁盘映像中挂载指定的分区到本地 Linux 文件系统呢?理论上说,可以用 dd 把该分区从磁盘映像中提取出来再挂载,不过 mount 提供了针对 loop 设备的偏移量参数,方便直接从磁盘映像中挂载指定分区。笔记如下:

      演示用的磁盘映像使用 qemu-img 制作。我们使用原生的 raw 格式,等价于磁盘上的原始数据流,保证它在任何 Linux 系统上都可以直接挂载。使用 Windows PE 工具盘启动该 qemu 虚拟机,创建一系列不同格式的分区并在其中建立几个文件。

root@lj-laptop:/opt/vm# qemu-img create -f raw vmtest.img 5Groot@lj-laptop:/opt/vm# qemu -hda ./vmtest.img -cdrom /dev/cdrom -boot d -m 256M -localtime

      磁盘分区结构如截图:

    从磁盘映像中挂载或提取指定分区

      回到宿主系统,使用 fdisk 的 -l、-u 参数查看磁盘映像。其中 -u 表示以扇区为单位显示分区起止位置,方便后续计算。

root@lj-laptop:/opt/vm# fdisk -l -u vmtest.img You must set cylinders.You can do this from the extra functions menu. Disk vmtest.img: 0 MB, 0 bytes255 heads, 63 sectors/track, 0 cylinders, total 0 sectorsUnits = sectors of 1 * 512 = 512 bytesDisk identifier: 0xbd86bd86      Device Boot      Start         End      Blocks   Id  Systemvmtest.img1              63     8193149     4096543+  83  Linuxvmtest.img2         8193150    10249469     1028160    5  Extendedvmtest.img3        10249470    10474379      112455    6  FAT16vmtest.img5         8193213     8610839      208813+  83  Linuxvmtest.img6         8610903     9028529      208813+  82  Linux swap / Solarisvmtest.img7         9028593    10249469      610438+   b  W95 FAT32

      这时我们只需要为 mount 添加 offset 参数,指定分区在磁盘映像中的逻辑地址,即可挂载这一分区。注意 offset 的单位是字节,通常一个扇区是 512 字节,因此需要用 fdisk 输出的 Start 乘以 512。以 vmtest.img3 分区为例。

root@lj-laptop:/opt/vm# mount -o loop,offset=$((10249470*512)) vmtest.img ./part/root@lj-laptop:/opt/vm# ls ./part/InFAT16.txtroot@lj-laptop:/opt/vm# umount ./part/

      如果有必要,我们可以将特定的分区从硬盘映像中提取出来,方便单独使用。通过 dd 可以完成提取,简便起见使用扇区大小 512 字节作为 bs 参数,这样 skip、count 参数很容易从 fdisk 的输出中计算出来。下面提取 vmtest.img5。

root@lj-laptop:/opt/vm# dd if=vmtest.img of=linux2.img bs=512 skip=8193213 count=$((8610839-8193213+1))417627+0 records in417627+0 records out213825024 bytes (214 MB) copied, 4.67434 s, 45.7 MB/sroot@lj-laptop:/opt/vm# mount -o loop linux2.img ./part/root@lj-laptop:/opt/vm# ls ./part/InLinux2.txt  lost+foundroot@lj-laptop:/opt/vm# umount ./part/

      到这一步,我们已经实现了从磁盘映像中挂载或提取指定分区。其中 fdisk 帮我们完成了磁盘映像的分析,直接将分区的逻辑地址显示给了我们。现在我们再借机复习一下磁盘分区表的格式,试试手工计算相关地址。这里推荐大家阅读网上这篇《解读 Windows 操作系统分区表的秘密》,其中详解过的概念这里不再赘述,下面的内容权当对这篇文章在 Linux 平台下的补充。

      首先查看磁盘映像的主引导扇区,其中分区表位于 0x1be 开始的 64 字节。

root@lj-laptop:/opt/vm# cat vmtest.img | xxd | head -32...00001b0: 0000 0000 0000 0000 86bd 86bd 0000 0001  ................00001c0: 0100 83fe 7ffd 3f00 0000 3f04 7d00 0000  ......?...?.}...00001d0: 41fe 05fe bf7d 7e04 7d00 8060 1f00 0000  A....}~.}..`....00001e0: 817e 06fe bf8b fe64 9c00 8e6e 0300 0000  .~.....d...n....00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.

      对于 vmtest.img1 和 vmtest.img3 这两个主分区,我们读出它们的起始逻辑地址分别为 0x3f 和 0x9c64fe(注意在分区表中以 Little-endian 存储),换算成十进制与 fdisk 输出的一致。bash 的算术表达式支持十六进制字面值,挂载方式同上。

root@lj-laptop:/opt/vm# mount -o loop,offset=$((0x3f*512)) vmtest.img ./part/root@lj-laptop:/opt/vm# ls ./part/InLinux.txt  lost+foundroot@lj-laptop:/opt/vm# umount ./part/root@lj-laptop:/opt/vm# mount -o loop,offset=$((0x9c64fe*512)) vmtest.img ./part/root@lj-laptop:/opt/vm# ls ./part/InFAT16.txtroot@lj-laptop:/opt/vm# umount ./part/

      对于扩展分区 vmtest.img2,我们通过 dd 定位到它所指向的第一个逻辑分区 vmtest.img5 前面的卷引导记录,查看逻辑分区的链式分区表。

root@lj-laptop:/opt/vm# dd if=vmtest.img bs=512 skip=$((0x7d047e)) | xxd | head -32...00001b0: 0000 0000 0000 0000 0000 0000 0000 0001  ................00001c0: 41fe 83fe bf17 3f00 0000 5b5f 0600 0000  A.....?...[_....00001d0: 8118 05fe bf31 9a5f 0600 9a5f 0600 0000  .....1._..._....00001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.

      vmtest.img5 相对于 vmtest.img2 的偏移量为 0x3f,按此地址挂载。

root@lj-laptop:/opt/vm# mount -o loop,offset=$(((0x7d047e+0x3f)*512)) vmtest.img ./part/root@lj-laptop:/opt/vm# ls ./part/InLinux2.txt  lost+foundroot@lj-laptop:/opt/vm# umount ./part/

      沿着链式分区表的第二条记录(即链表指针)指示的偏移量,我们可以找到第二、第三个逻辑分区(vmtest.img6、vmtest.img7)前面的卷引导记录以及这两个分区的逻辑地址。

root@lj-laptop:/opt/vm# dd if=vmtest.img bs=512 skip=$((0x7d047e+0x65f9a)) | xxd | head -32...00001b0: 0000 0000 0000 0000 0000 0000 0000 0001  ................00001c0: 8118 82fe bf31 3f00 0000 5b5f 0600 0000  .....1?...[_....00001d0: 8132 05fe bf7d 34bf 0c00 4ca1 1200 0000  .2...}4...L.....00001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.root@lj-laptop:/opt/vm# dd if=vmtest.img bs=512 skip=$((0x7d047e+0xcbf34)) | xxd | head -32...00001b0: 0000 0000 0000 0000 0000 0000 0000 0001  ................00001c0: 8132 0bfe bf7d 3f00 0000 0da1 1200 0000  .2...}?.........00001d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................00001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.

      取得了相应的地址,挂载或提取分区当然是轻而易举的。下面挂载了 vmtest.img7、提取了 vmtest.img5。

root@lj-laptop:/opt/vm# mount -o loop,offset=$(((0x7d047e+0xcbf34+0x3f)*512)) vmtest.img ./part/root@lj-laptop:/opt/vm# ls ./part/InFAT32.txtroot@lj-laptop:/opt/vm# umount ./part/root@lj-laptop:/opt/vm# dd if=vmtest.img of=linux2.img bs=512 skip=$((0x7d047e+0x3f)) count=$((0x65f5b))417627+0 records in417627+0 records out213825024 bytes (214 MB) copied, 4.65149 s, 46.0 MB/sroot@lj-laptop:/opt/vm# mount -o loop ./linux2.img ./part/root@lj-laptop:/opt/vm# ls ./part/InLinux2.txt  lost+foundroot@lj-laptop:/opt/vm# umount ./part/

同分类推荐文章

  1. 从零重建 macOS 开发机:可复现的环境初始化流程 (2026-06-14 20:36:00)
  2. 百度物理网络监控工具开源第二弹:毫秒级监控工具 baize,让你的网络问题无处遁形 (2026-06-11 08:10:28)
  3. How to Set Up Homebrew Tap for Private CLI Tools: A Complete Guide (2026-05-27 02:13:03)

查看更多 DevOps 文章 →

建议继续学习

  1. Linux如何统计进程的CPU利用率 (累计阅读 16,308)
  2. 我的 RHCA 之路 (累计阅读 14,013)
  3. Linux内存点滴 用户进程内存空间 (累计阅读 13,232)
  4. 给程序员新手的一些建议 (累计阅读 13,090)
  5. Linux 性能监控、测试、优化工具 (累计阅读 13,013)
  6. 关于linux内存free的一些事情 (累计阅读 12,869)
  7. ps - 按进程消耗内存多少排序 (累计阅读 12,690)
  8. Google怎么用linux (累计阅读 12,582)
  9. Linux Used内存到底哪里去了? (累计阅读 11,868)
  10. find命令的一点注意事项 (累计阅读 11,867)