C: 如何使用 mount(2) 挂载使用 mkfs 创建的常规文件系统?
C: How to mount a regular filesystem created with mkfs using mount(2)?
这就是我制作 "regular" 文件系统的方式:
$ touch container
$ mkfs.ext4 container 20000
如何使用 C 函数挂载它 mount(2)?
实际上 mount 告诉我:
Block device required
有没有办法在 C 中创建文件系统?
问题是 mount
库调用没有设置循环设备。为了挂载你的容器,你需要将 -o loop
传递给 mount
命令,它有效地包含了 losetup
所做的事情(即使 /dev/loopN
指向你的文件并且安装那个)。使用库调用时,需要模拟一下,即需要先设置一个loop device
要准确确定您想要做什么,请尝试:
strace mount -t ext4 -o loop container /mnt
并查看系统调用。您可以看到发生的事情是,首先它创建了一个循环设备(例如 /dev/loop0
使用等效于 losetup
的系统调用),然后它安装了该循环设备。
以下是 strace
输出中的关键行:
首先分配循环设备:
stat("/dev/loop", 0x7fffe90b00b0) = -1 ENOENT (No such file or directory)
open("/dev/loop0", O_RDONLY) = 3
fstat(3, {st_mode=S_IFBLK|0660, st_rdev=makedev(7, 0), ...}) = 0
ioctl(3, LOOP_GET_STATUS, {number=39736224, offset=0x6f726763, encrypt_type=0x732f7075 /* LO_CRYPT_??? */, encrypt_key_size=1702130553, flags=LO_FLAGS_READ_ONLY|LO_FLAGS_AUTOCLEAR|LO_FLAGS_PARTSCAN|0x63206460, name="group rw,noexec,nosuid,nodev,none,name=systemd 0 0", encrypt_key="s 0 0[=11=][=11=]e-agent.devices 0 0[=11=][=11=]07[=11=][=11=]", ...}) = -1 ENXIO (No such device or address)
close(3) = 0
open("/home/amb/so/container", O_RDWR) = 3
open("/dev/loop0", O_RDWR) = 4
readlink("/home", 0x7fffe90adfa0, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/amb", 0x7fffe90adfa0, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/amb/so", 0x7fffe90adfa0, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/amb/so/container", 0x7fffe90adfa0, 4096) = -1 EINVAL (Invalid argument)
ioctl(4, LOOP_SET_FD, 0x3) = 0
close(3) = 0
ioctl(4, LOOP_SET_STATUS64, {offset=0, number=0, flags=LO_FLAGS_AUTOCLEAR, file_name="/home/amb/so/container", ...}) = 0
ioctl(4, LOOP_GET_STATUS64, {offset=0, number=0, flags=LO_FLAGS_AUTOCLEAR, file_name="/home/amb/so/container", ...}) = 0
然后才做 mount
:
mount("/dev/loop0", "/mnt", "ext4", MS_MGC_VAL, NULL) = 0
但是我建议你 shell 到 mount
除非你有充分的理由不这样做。这确保 /etc/mtab
等得到维护。
作为 abligh 回答的后续,设置循环设备的代码是
int device = open(device_path, O_RDWR);
/* omitting error checking on device for clarity */
char buf[20];
int success = 0;
for (i = 0; i < 999999999) {
sprintf(buf, "/dev/loop%d", i);
int h = open(buf, O_RDWR);
if (h > -1) {
int r= ioctl(h, LOOP_SET_FD, device);
close(h);
if (!r) {
success = 1;
break;
}
} else if (errno == ENOENT)
break;
}
if (!success) {
/* no more free loop devices or you're not root */
}
这就是我制作 "regular" 文件系统的方式:
$ touch container
$ mkfs.ext4 container 20000
如何使用 C 函数挂载它 mount(2)?
实际上 mount 告诉我:
Block device required
有没有办法在 C 中创建文件系统?
问题是 mount
库调用没有设置循环设备。为了挂载你的容器,你需要将 -o loop
传递给 mount
命令,它有效地包含了 losetup
所做的事情(即使 /dev/loopN
指向你的文件并且安装那个)。使用库调用时,需要模拟一下,即需要先设置一个loop device
要准确确定您想要做什么,请尝试:
strace mount -t ext4 -o loop container /mnt
并查看系统调用。您可以看到发生的事情是,首先它创建了一个循环设备(例如 /dev/loop0
使用等效于 losetup
的系统调用),然后它安装了该循环设备。
以下是 strace
输出中的关键行:
首先分配循环设备:
stat("/dev/loop", 0x7fffe90b00b0) = -1 ENOENT (No such file or directory)
open("/dev/loop0", O_RDONLY) = 3
fstat(3, {st_mode=S_IFBLK|0660, st_rdev=makedev(7, 0), ...}) = 0
ioctl(3, LOOP_GET_STATUS, {number=39736224, offset=0x6f726763, encrypt_type=0x732f7075 /* LO_CRYPT_??? */, encrypt_key_size=1702130553, flags=LO_FLAGS_READ_ONLY|LO_FLAGS_AUTOCLEAR|LO_FLAGS_PARTSCAN|0x63206460, name="group rw,noexec,nosuid,nodev,none,name=systemd 0 0", encrypt_key="s 0 0[=11=][=11=]e-agent.devices 0 0[=11=][=11=]07[=11=][=11=]", ...}) = -1 ENXIO (No such device or address)
close(3) = 0
open("/home/amb/so/container", O_RDWR) = 3
open("/dev/loop0", O_RDWR) = 4
readlink("/home", 0x7fffe90adfa0, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/amb", 0x7fffe90adfa0, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/amb/so", 0x7fffe90adfa0, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/amb/so/container", 0x7fffe90adfa0, 4096) = -1 EINVAL (Invalid argument)
ioctl(4, LOOP_SET_FD, 0x3) = 0
close(3) = 0
ioctl(4, LOOP_SET_STATUS64, {offset=0, number=0, flags=LO_FLAGS_AUTOCLEAR, file_name="/home/amb/so/container", ...}) = 0
ioctl(4, LOOP_GET_STATUS64, {offset=0, number=0, flags=LO_FLAGS_AUTOCLEAR, file_name="/home/amb/so/container", ...}) = 0
然后才做 mount
:
mount("/dev/loop0", "/mnt", "ext4", MS_MGC_VAL, NULL) = 0
但是我建议你 shell 到 mount
除非你有充分的理由不这样做。这确保 /etc/mtab
等得到维护。
作为 abligh 回答的后续,设置循环设备的代码是
int device = open(device_path, O_RDWR);
/* omitting error checking on device for clarity */
char buf[20];
int success = 0;
for (i = 0; i < 999999999) {
sprintf(buf, "/dev/loop%d", i);
int h = open(buf, O_RDWR);
if (h > -1) {
int r= ioctl(h, LOOP_SET_FD, device);
close(h);
if (!r) {
success = 1;
break;
}
} else if (errno == ENOENT)
break;
}
if (!success) {
/* no more free loop devices or you're not root */
}