1. 前言
限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。
2. 什么是 loop device?
Linux allows users to create a special block device by which they can map a normal file to
a virtual block device.
所谓的 loop device
,就是一类特殊的虚拟块设备(block device)
,允许像访问块设备(block device)
一样访问普通文件(normal file)
,也就是loop device
将普通文件(normal file)
当作存储介质。
3. loop device 典型应用场景
譬如在制作根文件系统时,核心步骤如下:
1. 用 dd 创建一个文件镜像
2. 用 mkfs 格式成需要的格式
3. 建立一个临时目录 temp
4. 将文件镜像 mount 到 temp 目录
5. 在 temp 目录下建立根文件系目录
6. umount temp 目录
这里就是将文件镜像当作块设备一样访问,这需要 loop device
的支持,否则将操作失败。譬如下面是一个制作 ext4
根文件系统的核心步骤:
dd if=/dev/zero of=rootfs.ext4 bs=1M count=2048 > /dev/null 2>&1
mkfs.ext4 -F -L linuxroot rootfs.ext4
mkdir temp
mount rootfs.ext4 temp # 这里需要 loop device 支持, 否则无法操作成功
......
umount temp
4. 内核 loop device 支持
要开启 loop device
虚拟块设备功能,需要开启内核配置项 CONFIG_BLK_DEV_LOOP
,具体功能实现在 drivers/block/loop.c
中。可以通过查看是否生成了 loop device
设备节点,来确认内核是否开启 loop device
支持:
$ ls -l /dev/loop*
brw-rw---- 1 root disk 7, 0 11月 10 16:33 /dev/loop0
brw-rw---- 1 root disk 7, 1 11月 10 14:36 /dev/loop1
brw-rw---- 1 root disk 7, 2 11月 10 09:50 /dev/loop2
brw-rw---- 1 root disk 7, 3 11月 10 09:50 /dev/loop3
brw-rw---- 1 root disk 7, 4 11月 10 09:50 /dev/loop4
brw-rw---- 1 root disk 7, 5 11月 10 09:50 /dev/loop5
brw-rw---- 1 root disk 7, 6 11月 10 09:50 /dev/loop6
brw-rw---- 1 root disk 7, 7 11月 10 09:50 /dev/loop7
crw-rw---- 1 root disk 10, 237 11月 10 09:50 /dev/loop-control
其中设备 /dev/loop-control
是用来设置和控制块设备的字符设备节点,其它的 /dev/loop[0-7]
是虚拟块设备。初始虚拟块设备的个数可通过内核配置项 CONFIG_BLK_DEV_LOOP_MIN_COUNT
进行调整,默认是 8
个。
5. loop device 相关工具
losetup
是一个设置和控制 loop device
的工具,下面给出一个关联 loop device
和 普通文件的例子:
$ losetup -f # 查询第一个空闲可用的 loop device
/dev/loop0
$ sudo losetup /dev/loop0 /path/to/test.img # 关联 loop device 和 普通文件 test.img
$ losetup -l # 查询 关联
NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE
/dev/loop0 0 0 0 0 /path/to/test.img
$ sudo mount /dev/loop0 /path/to/mnt/dir # 挂载 loop device (test.img) 到 指定目录
$ sudo umount /dev/loop0 # 卸载
$ sudo losetup -d /dev/loop0 # 接除 loop device 和 普通文件 test.img 的 关联
更多关于工具 losetup
的细节请参考其 man 手册。
上面是一个直接使用 loop device
的例子,再来看一个间接、隐式使用 loop device
的例子。笔者挂载了一个 ext4
的根文件系统到 temp
目录,然后分别通过 mount, lsblk, losetup
来查询挂载状态:
$ sudo mount rootfs/arm-ubuntu-16.04.img temp # 隐式关联 /dev/loop0 和 arm-ubuntu-16.04.img
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 1024M 0 rom
loop0 7:0 0 2G 0 loop /home/XXX/qemu-lab/arm-ubuntu/temp
sda 8:0 0 80G 0 disk
├─sda2 8:2 0 1K 0 part
├─sda5 8:5 0 975M 0 part [SWAP]
└─sda1 8:1 0 79G 0 part /
$ mount | grep ext4
/home/XXX/qemu-lab/arm-ubuntu/rootfs/arm-ubuntu-16.04.img on /home/XXX/qemu-lab/arm-ubuntu/temp type ext4 (rw,relatime,data=ordered)
$ losetup -a
/dev/loop0: []: (/home/XXX/qemu-lab/arm-ubuntu/rootfs/arm-ubuntu-16.04.img)
$ losetup -l
NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE
/dev/loop0 0 0 1 0 /home/XXX/qemu-lab/arm-ubuntu/rootfs/arm-ubuntu-16.04.img