3 个版本
0.1.2 | 2020 年 1 月 2 日 |
---|---|
0.1.1 | 2020 年 1 月 2 日 |
0.1.0 | 2020 年 1 月 2 日 |
#1219 in 文件系统
17KB
225 行
vblk
本库提供了一个接口,用于创建虚拟块设备,这些设备在读写操作时调用您的 Rust 代码。这类似于 FUSE,但您只暴露一个固定大小的文件作为块设备,而不是整个文件系统。如果您需要与远程块设备接口,但没有方便的方式挂载它,或者用于原型设计块设备驱动程序,这将很有用。
这是通过(滥用)Linux 内核的 NBD 驱动程序来实现的,而不是实现一个新的通用块设备驱动程序;在 Rust 应用程序中启动了一个基本的 NBD 客户端,用于处理 NBD 请求,这些请求通过 Unix 域套接字在内核驱动程序之间传递。大多数情况下这是通过分叉来完成的;在这个库中,启动了一个单独的线程来托管内核端的 NBD 服务器。
此库仅适用于 Linux 2.6 及以上版本,并且默认情况下需要安装和加载 NBD 内核模块。它还默认需要 root 权限。较新的 NBD 功能,如 FLUSH
和 TRIM
命令,可能仅在较新的 Linux 内核版本中可用;对于较旧版本,这些命令的 Rust 处理器将根本不会被调用。
用法
假设您有适当的权限并且已加载 NBD 模块,以下示例将在 /dev/nbd0
上挂载一个虚拟块设备,该设备将读取整个块设备上的 0xDEADBEEF
。由于未指定写入处理程序,因此将拒绝写入块设备的请求。您可以在 examples/deadbeef.rs
中找到并运行此示例,还有一个 ramdisk 示例展示了写入的工作原理,在 examples/ramdisk.rs
中。
use std::io::Error;
use vblk::{mount, BlockDevice};
struct DeadbeefDevice;
impl BlockDevice for DeadbeefDevice {
fn read(&mut self, offset: u64, bytes: &mut [u8]) -> Result<(), Error> {
for (index, byte) in bytes.iter_mut().enumerate() {
*byte = match (index as u64 + offset) % 4 {
0 => 0xDE,
1 => 0xAD,
2 => 0xBE,
_ => 0xEF,
};
}
Ok(())
}
fn block_size(&self) -> u32 {
1024
}
fn blocks(&self) -> u64 {
4096 // 4MB device
}
}
fn main() {
unsafe { mount(&mut DeadbeefDevice, "/dev/nbd0", |_device| Ok(())).unwrap() };
}
启动后,您应该能够访问和读取块设备
# xxd /dev/nbd0 | head -n 2
00000000: dead beef dead beef dead beef dead beef ................
00000010: dead beef dead beef dead beef dead beef ................
# blockdev --getsize64 /dev/nbd0
4194304
但尝试写入块设备将失败,因为我们没有提供 write
处理程序,如下所示。请注意,oflag=dsync
参数在这里很重要,否则写入将缓存在内核中,并异步写入,您将在 dmesg
中找到写入错误。
# dd oflag=dsync if=/dev/zero of=/dev/nbd0 bs=1024 count=4096
dd: error writing '/dev/nbd0': Input/output error
1+0 records in
0+0 records out
0 bytes copied, 0.000263995 s, 0.0 kB/s
卸载
虚拟块设备只有在NBD连接优雅地中断时,其unmount
处理程序才会被调用,因此默认情况下,仅发送Ctrl+C到您的应用程序不会执行此操作。您传递给mount
函数的回调返回一个拥有的Device
结构体,该结构体上有一个unmount
方法;该结构体旨在存储在某个地方,并在您的应用程序需要关闭时使用。您不得在callback
中阻塞;块设备将在返回之前不会挂载。
以下示例显示了如何使用ctrlc
包,通过截获Ctrl+C并卸载块设备,这将导致mount
方法优雅地返回。
权限
默认情况下,在大多数发行版中,只有root(或disk
组的用户)可以与NBD内核模块和NBD块设备交互。我还没有尝试过,但根据您的环境,应该可以通过例如udev
规则配置NBD设备驱动程序。
许可证
本软件依据MIT许可证提供。
依赖项
约4.5MB
约96K SLoC