问题描述
几乎所有的Linux发行版在安装期间都会调用一个应用程序,该应用程序会将存储驱动器格式化为ext2 / 3/4文件系统。 怎么做?它可以通过任何UEFI应用程序实现吗?
解决方法
文件系统的创建与UEFI无关。
Unix方法是将硬件资源公开为伪文件(reference),以便可以使用标准文件命令来访问硬件。如果是HDD或SDD,则可以通过设备节点(例如/dev/sda
,/dev/sdb
)访问原始驱动器。根据硬件的不同,您可能还会使用诸如/dev/nvme0n1
之类的名称。您可以打开这些文件并像对待其他文件一样操作它们(例如,在C中使用fopen
,fread
,fseek
等)。 Linux内核会将对这些伪文件的任何写或读操作映射到原始驱动器。
通常,您希望在应用文件系统之前对驱动器进行分区(这样可以将文件系统直接应用于整个驱动器而不进行任何分区)。要创建分区,您需要将分区表(例如GPT格式)写入驱动器的开头。然后,您可以在分区表中为分区创建条目。创建分区后,Linux应将每个分区公开为单独的设备节点(例如/dev/sda1
,/dev/sda2
或/dev/nvme0n1p1
,/dev/nvme0n1p2
)。这些文件可以像其他文件一样再次打开和处理。考虑到分区的偏移量,Linux内核将再次将对这些文件的写入或读取操作映射到原始驱动器。
要在分区上创建文件系统,您将使用诸如mkfs.ext4
(e2fsprogs的一部分)之类的工具。 mkfs.ext4
将打开该分区的分区伪文件,并将文件系统数据结构写入该文件。 Linux内核会将写操作映射到原始驱动器上。
让我们考虑以下示例。我们将创建一个新文件,并使Linux内核假装该文件是驱动器(使用循环设备)。然后,我们将在此“驱动器”上创建一个新的分区表,然后在其分区之一上创建一个文件系统。
-
创建一个大小为2G的文件,将其用作我们的驱动器:
# dd if=/dev/zero of=my_disk bs=1024 count=2000000 2000000+0 records in 2000000+0 records out 2048000000 bytes (2,0 GB,1,9 GiB) copied,8,13332 s,252 MB/s
-
创建一个循环设备,使我们可以将文件视为新驱动器:
# losetup -f /dev/loop0 # losetup -P /dev/loop0 my_disk
-
在磁盘上创建分区表:
# fdisk /dev/loop0 Command: g Created a new GPT disklabel (GUID: 8155F57B-0E54-1146-9CC1-E5092C1F671C). Command: n Partition number (1-128,default 1): First sector (2048-3999966,default 2048): Last sector,+/-sectors or +/-size{K,M,G,T,P} (2048-3999966,default 3999966): Created a new partition 1 of type 'Linux filesystem' and of size 1,9 GiB. Command: w
您现在应该可以看到新创建的分区的新设备节点
/dev/loop0p1
。如果没有尝试,请尝试类似partprobe
之类的方法来通知内核分区布局的更改,或者使用losetup -d /dev/loop0
删除循环设备,然后通过上一步再次打开它。 -
在驱动器的分区上创建文件系统:
# mkfs.ext4 /dev/loop0p1 mke2fs 1.45.6 (20-Mar-2020) Discarding device blocks: done Creating filesystem with 499739 4k blocks and 125184 inodes Filesystem UUID: 09d1a2e7-4ef1-4a89-92ab-eae1a80d9534 Superblock backups stored on blocks: 32768,98304,163840,229376,294912 Allocating group tables: done Writing inode tables: done Creating journal (8192 blocks): done Writing superblocks and filesystem accounting information: done
您还可以应用
strace
来观察mkfs.ext4
使用的系统调用。您应该能够看到open
的{{1}}和close
呼叫,还有一些/dev/loop0p1
和read
的呼叫。您应该看不到任何写操作。这是因为lseek
似乎改用mkfs.ext4
(reference),其中文件的一部分被映射到内存中,这样,对内存的修改将被文件写入到文件中内核(比手动将文件的一部分读取到缓冲区,修改缓冲区并将缓冲区写回到文件中要快一些)。但是内存映射并不特定于作为分区设备节点的文件,您也可以在常规文件上使用mmap
。 -
安装文件系统:
mmap
例如,您可以然后在
# mount /dev/loop0p1 /mnt
中创建一个文件,卸载该文件系统,然后再次安装它以确认该文件已在我们的新驱动器上创建。
您可以看到在示例中ext4文件系统是通过访问驱动器分区的设备节点而创建的。在安装典型的Linux发行版期间,将以相同的方式创建文件系统,除了在实际驱动器上使用分区的设备节点,而不是在本示例中使用的循环设备。
参考: