我正在为嵌入式系统构建磁盘映像(放置在 4GB SD 卡上)。我希望系统有两个分区。一个“根”分区(200Mb)和一个“数据”分区(800Mb)。
我用 dd 创建了一个 1GB 的空文件。然后我使用parted来设置分区。我将它们分别安装在循环设备中,然后格式化它们; ext2 代表“根” ext4 代表“数据”。将我的根文件系统添加到“根”分区并将“数据”留空。
问题就在这里。我现在被一个 1GB 的图像困住了,上面只有 200MB 的数据。理论上,我不应该能够将映像截断为 201MB 并且仍然可以安装文件系统吗?不幸的是我还没有发现这种情况。
我记得过去使用过 Freescale 的构建环境,该环境用于创建 30Mb 映像,该环境具有用于利用整个 4GB SD 卡的分区。不幸的是,此时我无法找到他们是如何做到这一点的。
我已经阅读了 ext 文件系统的磁盘格式,如果第一个超级块之后的任何内容中都没有数据(备份超级块和未使用的块表除外),我想我可以在那里截断。
不幸的是,当我这样做时,安装系统崩溃了。然后我可以运行 FSCK,恢复超级块和块表,然后挂载它就没有问题了。我只是认为没有必要。
也许不同的文件系统可以工作?有任何想法吗?
谢谢,
编辑
更改分区以读取文件系统。分区仍然存在并且没有改变,但是截断映像后文件系统被破坏。
编辑
我发现这种情况是,当我将文件截断到仅大于第一组“数据”分区超级块和索引节点/块表的大小时(在数据块范围内的某个位置),文件系统无需执行任何操作即可卸载用于恢复其余超级块和块/索引节点表的 fsck
答案1
最简单的方法是将支持文件创建为稀疏文件;也就是说,将其设置为 1GB,truncate -s 1G disk.img
而不是dd if=/dev/zero bs=1048576 count=1024 of=disk.img
(或其他)。很好,truncate
也快得多。
如果您ls -l
对该文件执行 操作,它将显示为 1GB,但这只是其表面大小。du disk.img
将给出实际尺寸。
(注意,您需要将映像放在支持稀疏文件的文件系统上。所有常见的 Unix 都支持。Ext2/3/4 都支持。FAT32 不支持。HFS+ 也不支持。)
注意:从逻辑上讲,稀疏文件仍然是完整大小。只是从未写入的部分并未物理存储在磁盘上。在大多数情况下,未实际存储的部分对程序是隐藏的。不过,一些实用程序支持它。 (例如,,,dd conv=sparse
等cp --sparse=auto/always
)。一个真正的 USB 记忆棒不能稀疏。如果你用dd conv=sparse
它来编写它,它可能会快得多,但你会留下之前存在的任何数据,而不是预期的充满 NUL (0x00) 的块。应该可以正常工作(因为它的可用空间),但会在 USB 记忆棒上留下旧数据 - 可能是一个安全问题。
答案2
首先,将稀疏图像写入磁盘不是导致除了该图像文件的整个大小(漏洞和所有内容)覆盖磁盘之外的任何内容。这是因为处理稀疏文件的数量是文件系统的质量 - 也是原始设备(例如您写入图像的那个)没有这样的东西然而。稀疏文件可以是已存储安全可靠地存储在由文件系统控制的介质上明白稀疏文件(例如 ext4 设备)但一旦你把它写出来,它就会包含你想要表达的一切。所以你应该做的是:
只需将其存储在能够识别稀疏文件的文件系统上,直到您准备好写入它为止。
让它深两层...
也就是说,将您的主图像写入一个文件,创建另一个家长具有可以理解稀疏文件的 fs 的图像,然后将图像复制到家长图像,以及...
当需要编写图像时,首先编写您的父图像,然后编写您的主图像。
以下是第 2 步的操作方法:
创建一个 1GB 稀疏文件...
dd bs=1kx1k seek=1k of=img </dev/null
写两个
ext4
对其分区表进行分区:1 200MB、2 800MB...printf '%b\n\n\n\n' n '+200M\nn\n' 'w\n\c' | fdisk img
创建两个
ext4
文件系统位于-P
分配的循环设备上,并将第二个文件系统的副本放在第一个文件系统上......sudo sh -c ' for p in "$(losetup --show -Pf img)p"* ### the for loop will iterate do mkfs.ext4 "$p" ### over fdisks two partitions mkdir -p ./mnt/"${p##*/}" ### and mkfs, then mount each mount "$p" ./mnt/"${p##*/}" ### on dirs created for them done; sync; cd ./mnt/*/ ### next we cp a sparse image cp --sparse=always "$p" ./part2 ### of part2 onto part1 dd bs=1kx1k count=175 </dev/zero >./zero_fill ### fill out part1 w/ zeroes sync; cd ..; ls -Rhls . ### sync, and list contents umount */; losetup -d "${p%p*}" ### last umount, destroy rm -rf loop*p[12]/ ' ### loop devs and mount dirs
mke2fs 1.42.12 (29-Aug-2014) Discarding device blocks: done Creating filesystem with 204800 1k blocks and 51200 inodes Filesystem UUID: 2f8ae02f-4422-4456-9a8b-8056a40fab32 Superblock backups stored on blocks: 8193, 24577, 40961, 57345, 73729 Allocating group tables: done Writing inode tables: done Creating journal (4096 blocks): done Writing superblocks and filesystem accounting information: done mke2fs 1.42.12 (29-Aug-2014) Discarding device blocks: done Creating filesystem with 210688 4k blocks and 52752 inodes Filesystem UUID: fa14171c-f591-4067-a39a-e5d0dac1b806 Superblock backups stored on blocks: 32768, 98304, 163840 Allocating group tables: done Writing inode tables: done Creating journal (4096 blocks): done Writing superblocks and filesystem accounting information: done 175+0 records in 175+0 records out 183500800 bytes (184 MB) copied, 0.365576 s, 502 MB/s ./: total 1.0K 1.0K drwxr-xr-x 3 root root 1.0K Jul 16 20:49 loop0p1 0 drwxr-xr-x 2 root root 40 Jul 16 20:42 loop0p2 ./loop0p1: total 176M 12K drwx------ 2 root root 12K Jul 16 20:49 lost+found 79K -rw-r----- 1 root root 823M Jul 16 20:49 part2 176M -rw-r--r-- 1 root root 175M Jul 16 20:49 zero_fill ./loop0p1/lost+found: total 0 ./loop0p2: total 0
现在有很多输出 - 大部分来自
mkfs.ext4
- 但请特别注意ls
底部的位。ls -s
将显示实际的-s
尺寸磁盘上文件的名称 - 它始终显示在第一列中。现在我们基本上可以将图像缩小到只有第一个分区......
fdisk -l img
Disk img: 1 GiB, 1073741824 bytes, 2097152 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xc455ed35 Device Boot Start End Sectors Size Id Type img1 2048 411647 409600 200M 83 Linux img2 411648 2097151 1685504 823M 83 Linux
告诉
fdisk
我们第一个分区中有 411647 +1 512 字节扇区img
...dd seek=411648 of=img </dev/null
这会截断
img
仅将文件保存到其第一个分区。看?ls -hls img
181M -rw-r--r-- 1 mikeserv mikeserv 201M Jul 16 21:37 img
...但我们仍然可以挂载该分区...
sudo mount "$(sudo losetup -Pf --show img)p"*1 ./mnt
...这是其内容...
ls -hls ./mnt
total 176M 12K drwx------ 2 root root 12K Jul 16 21:34 lost+found 79K -rw-r----- 1 root root 823M Jul 16 21:34 part2 176M -rw-r--r-- 1 root root 175M Jul 16 21:34 zero_fill
和我们可以将第二个分区的存储图像附加到第一个分区......
sudo sh -c ' dd seek=411648 if=./mnt/part2 of=img umount ./mnt; losetup -D mount "$(losetup -Pf --show img)p"*2 ./mnt ls ./mnt; umount ./mnt; losetup -D'
1685504+0 records in 1685504+0 records out 862978048 bytes (863 MB) copied, 1.96805 s, 438 MB/s lost+found
现在我们的
img
文件:它不再稀疏......ls -hls img
1004M -rw-r--r-- 1 mikeserv mikeserv 1.0G Jul 16 21:58 img
...但是第二次删除它和第一次一样简单,当然...
dd seek=411648 of=img </dev/null ls -hls img
181M -rw-r--r-- 1 mikeserv mikeserv 201M Jul 16 22:01 img
答案3
您是否想要使用 800MB 的空间创建此映像,以便可以复制到 SD 卡。但不想在存储图像时浪费空间。如果是这样,我可以建议压缩,例如bzip
.不过,这将取决于未使用的块被初始化为零。
答案4
希望我正确理解这个问题:
缩小文件系统和分区。使用gparted
。