Loopback Device

来自osdev
跳到导航 跳到搜索

环回设备(Loopback Device)是一种用于将文件解释为真实设备的机制。 这种方法的主要优点是,在真实磁盘上使用的所有工具都可以与环回设备一起使用。

注意:本文仅介绍UNIX环境(包括Cygwin)。 有关如何在Windows上使用环回设备的信息,请参阅 diskpart

Linux下的环回设备

Linux环回设备只能由root使用,在使用之前需要在内核中启用。

带有GRUB和EXT2的软盘映像

首先,让我们创建一个空映像。

dd if=/dev/zero of=floppy.img bs=512 count=2880

现在,让我们为挂载将其设置一下。(译者注:losetup是用于设置环回设备的Linux命令)

losetup /dev/loop0 floppy.img

现在让我们将其设置为EXT2格式。

mkfs -t ext2 /dev/loop0

挂载!

mount -t ext2 /dev/loop0 /mnt/myfloppy

创建GRUB目录。

cd /mnt/myfloppy
mkdir grub

复制GRUB的第二阶段文件。(GRUB阶段[12]也可以位于/usr/lib/GRUB/)

cp /lib/grub/i386-pc/stage[12] /mnt/myfloppy/grub

为GRUB安装创建设备映射。“你需要第一部分的引语。”

echo "(fd0) /dev/loop0" > /mnt/myfloppy/grub/device.map

启动GRUB控制台以安装到引导记录中。

grub --device-map=/mnt/myfloppy/grub/device.map /dev/loop0

在GRUB控制台中:

root (fd0)
setup (fd0)

注意:在使用仿真器直接读取/dev/loop0之前,必须先卸载/mnt/myfloppy,例如:

qemu -fda /dev/loop0

注意: 删除环回设备时,原始的floppy.img文件将与修改后的内容一起保存。

带有FAT16的软盘映像

创建空映像。

dd if=/dev/zero of=floppy.img bs=512 count=2880

挂载前设置。

losetup /dev/loop0 floppy.img

把它做成MSDOS格式。

mkdosfs /dev/loop0

挂载!

mount -t msdos /dev/loop0 /mnt/myfloppy

带FAT12的软盘映像

下面提到的步骤对BrokenThorn Entertainment教程很有用

创建空映像。

dd if=/dev/zero of=floppy.img bs=512 count=2880

挂载前设置。

losetup /dev/loop0 floppy.img

将其格式化为FAT12。

mkdosfs -F 12 /dev/loop0

挂载!

mount /dev/loop0 /mnt -t msdos -o "fat=12"

卸载

umount /mnt

销毁环回设备

losetup -d /dev/loop0

硬盘映像

硬盘映像包含一个MBR,然后包含许多分区,但是Linux中的 “mount” 指令适用于磁盘分区,而不是全磁盘。 要装载磁盘映像中包含的分区,我们需要确保“mount”命令只看到我们的分区,而不是整个磁盘。

创建映像

首先创建将用于磁盘映像的空文件。 我们假设磁盘的几何结构为#cylinders(柱面),16个磁头,63个扇区/磁道,512字节/扇区,这意味着每个柱面包含516096字节(16*63*512)。 确定你想要的磁盘映像的大小,并选择适当的柱面数量(我将始终使用#cylinders)。

示例: 如果我想要一个500Mb的磁盘,我会选择1000柱面 ((500*1000*1024)/516096的近似值)。

写入磁盘映像(我假设文件名为c.img):

dd if=/dev/zero of=/path/to/c.img bs=516096c count=#cylinders

说明:

dd 用于复制和转换文件的Linux命令
if=/dev/zero 源文件为/dev/ZERO,它是...*drumroll*...无限的零
of=/path/to/c.img 目标文件是我们的磁盘映像 (如果不存在,dd将创建该文件)
bs=516096c 意味着一次读写516096字节(这只是为了简单起见)
count=#cylinders 复制此数量的块。由于我们将bs设置为516096字节,因此每个块是一个柱面长

这给我们留下了一个装满零的大小合适的文件,我们将把它用于我们的磁盘映像。

分区

现在,要在磁盘映像上创建MBR和分区表(通常你需要是root用户)。

fdisk -u -C#cylinders -S63 -H16 /path/to/c.img

说明:

fdisk Linux DOS分区维护程序。
-u 以扇区而不是柱面显示单位(我们将需要此功能)。
-C#cylinders 将磁盘的柱面设置为我们的值。
-S63 将 扇区/轨道设置为63。
-H16 将 磁头/轨道设置为16。
/path/to/c.img fdisk is capable of partitioning image files directly.

在fdisk中使用以下命令:

o - 创建一个新的空DOS分区表。
n - 创建一个新分区(为简单起见,只创建一个覆盖整个磁盘的主分区)。
a - 切换可引导标志 (可选)。
p - 打印分区表。

你最终应该会得到一个如下所示的屏幕:

Disk /path/to/c.img: 516 MB, 516096000 bytes
16 heads, 63 sectors/track, 1000 cylinders, total 1008000 sectors
Units = sectors of 1 * 512 = 512 bytes
      Device    Boot      Start         End      Blocks   Id  System
/path/to/c.img1   *          63     1007999      503968+  83  Linux

显然,根据映像的大小,柱面数量,分区末端和块将有所不同。

记下起始扇区(此处63)和块计数(此处503968)。

注意:如果你打算将分区格式化为ext2fs以外的格式,那么在这里使用t命令更改分区id。 我还应该指出,磁盘制造商和程序员认为的每兆多少字节有差异。

w -将分区表写入“磁盘”并退出。

忽略有关重新读取分区表的任何错误。 因为这不是物理设备,我们真的不在乎。

我们现在在磁盘映像上有一个分区表。

不幸的是,这也意味着从现在开始,我们必须考虑这样一个事实,即我们的分区不是从映像的字节0开始的。

挂载

好的,现在我们将文件附加到环回设备,这样我们就可以在分区开始之前跳过所有内容。

losetup -o32256 /dev/loop0 /path/to/c.img

解释

-o32256 Move the start of data 32256 bytes into the file

我们将32256个字节移动到文件中的原因是这是分区开始的地方。 还记得我说过要注意分区的起始扇区吗(通常是63)? 因为每个扇区有512字节长,所以我们知道分区的起始字节是文件中的32256(63*512)字节。 造成这种差距的原因是,大多数 (没有真正标准的) fdisk程序除了MBR之外,没有使用第一个轨道。 然而,这些空间并不总是被浪费,一些引导加载程序(如GRUB)使用它来存储程序的部分内容。

注意:如果你没有使用建议的几何尺寸,那么你必须自己计算一下。

我们现在有一个设备 (/dev/loop0),我们可以以类似于普通分区 (例如/dev/hda1) 的方式使用它。

格式化分区

对于ext2fs,使用:

mke2fs -b1024 /dev/loop0 #blocks

说明:

mke2fs 创建一个EXT2文件系统
-b1024 使用块大小1024
/dev/loop0 创建文件系统的设备 (这里/dev/loop0是我们的 “分区”)
#blocks 记得我说过要注意fdisk部分的块数吗?这就是为什么。

这为我们提供了一个干净的ext2格式化分区。

注意: mke2fs足够聪明,可以自己找出块大小和 #blocks,但是如果你想使用多个分区,则需要知道如何使用这些值。

对于FAT32,请使用:

mkdosfs -F32 /dev/loop0 #blocks

说明:

mkdosfs 创建一个DOS文件系统 (在某些Linux系统上可能不存在,如果不存在,请搜索dosfstools软件包)
-F32 FAT 32分配表(如何使用FAT12/FAT16应该是显而易见的)
/dev/loop0 与ext2fs版本相同
#blocks 与ext2fs版本相同

这为我们提供了一个干净的FAT32格式分区(忽略软盘警告)。

注意:使用#blocks的原因与使用ext2fs相同,即可能有多个分区。

挂载分区

现在应该可以挂载分区了(因为它仍在环回设备上设置)。

命令:

mount -text2 /dev/loop0 /mnt/wherever

或者:

mount -tvfat /dev/loop0 /mnt/wherever

说明:

mount Linux命令挂载文件系统
-text2 / -tvfat 在使用文件系统时,Linux通常可以自己解决这个问题。
/dev/loop0 代表我们分区的设备
/mnt/wherever 用于挂载分区的目录。

这应该会为你留下一个挂载良好的分区。 如果你运行df-Th,你应该得到一条类似于:

Filesystem    Type    Size  Used Avail Use% Mounted on
/dev/loop0    vfat    492M  4.0K  492M   1% /mnt/wherever

...或对于ext2fs:

Filesystem    Type    Size  Used Avail Use% Mounted on
/dev/loop0    ext2    477M   13K  452M   1% /mnt/wherever

(是的,这些是针对同一磁盘映像的。默认情况下,ext2fs保留/使用相当多的空间,甚至是空的。)

卸载、分离

好的,卸载分区并分离环回设备。

命令:

umount /dev/loop0
losetup -d /dev/loop0

说明:

umount 用于卸载文件系统的Linux命令。
/dev/loop0 安装的设备

使之更容易

最后要做的一件事是简化该分区的挂载和卸载。

挂载:

mount -text2 -oloop=/dev/loop0,offset=32256 /path/to/c.img /mnt/wherever

卸载:

umount /path/to/c.img

这实质上是我们之前格式化分区时使用的losetup和mount命令的组合。 如果使用,这也意味着我们无法通过/dev/loop0访问原始 “磁盘” 或 “分区”。

另见 http://www.pixelbeat.org/scripts/lomount.sh

最后,如果你必须非常频繁地挂载和卸载该映像,并且你懒得每次都键入sudo密码,那么只需添加到/etc/fstab:

/path/to/c.img    /mnt/wherever    ext2    user,loop    0 0

现在你可以直接使用:

mount /mnt/wherever
umount /mnt/wherever

最后

就是这样,你现在知道如何在Linux下处理硬盘映像了。 安装时,你可以以与使用普通磁盘分区完全相同的方式使用它。 多个分区是它的扩展,只需根据要使用的分区(并使用正确的块数)更改losetup命令的偏移量。

要记住的事项:

  • losetup类型命令将为你提供与原始磁盘设备等效的命令 (例如/dev/hda)
  • losetup-o type命令将为你提供相当于原始分区设备(例如/dev/hda1)的功能

在操作挂载的磁盘映像上的文件时,不要忘记刷新文件系统缓冲区。 在类似Unix的系统上,这可以简单地通过在你的shell中执行 sync 程序来完成。

FreeBSD下的环回设备

FreeBSD使用mdconfig。 首先,使用DD创建一个空的软盘图像 (大小为1.44 MB)。 Memdisks是动态分配的,名称显示在mdconfig命令之后。 这里假设打印了“md0”。

要挂载:

dd if=/dev/zero of=floppy.img bs=512 count=2880
mdconfig -a -t vnode -f floppy.img
newfs_msdos -f 1440 /dev/md0
mount -t msdosfs /dev/md0 /mnt/myfloppy

要卸载:

umount /mnt/myfloppy
mdconfig -d -u md0

OpenBSD下的环回设备

OpenBSD使用了vnconfig(8),从版本2.2开始 (也许更早 ..)。

作为root用户或使用su/sudo,下面是一个配置vnode伪磁盘设备的示例场景。

使用dd创建floppy.img文件:

dd if=/dev/zero of=/path/to/floppy.img bs=512 count=2880

配置vnd0设备:

vnconfig vnd0 /path/to/floppy.img

列出已配置的设备:

vnconfig -l

输出:
   vnd0: covering floppy.img on wd0a, inode 270473
   vnd1: not in use
   vnd2: not in use
   vnd3: not in use

创建FAT12文件系统,然后挂载设备:

newfs_msdos -F 12 -f 1440 /dev/rvnd0c
mount -t msdos /dev/vnd0i /mnt/floppy

卸下设备安装并卸载vnd0设备:

umount /mnt/floppy
vnconfig -u vnd0

更多信息: vnd(4) / vnconfig(8)