1个不稳定版本

0.1.0 2020年12月14日

#620 in 内存管理

MIT 许可证

520KB
9K SLoC

刚玉:Rust中的持久内存编程库

crndm为Rust应用程序提供持久内存支持。这对于开发无需过多关注崩溃一致性和数据丢失的可靠持久内存应用程序很有用。

通过仔细使用Rust的严格类型检查规则和借用机制,crndm确保实现中不存在常见的持久内存相关错误。crndm使软件实现避免了以下类型的零持久内存相关问题

  • 指向易失性堆的持久指针,
  • 跨池指针,
  • 对数据的不可恢复修改,
  • 因电源故障导致的数据不一致,
  • 以及 Rust处理的全部内存相关问题。

开发者将在设计时看到这些问题。因此,这降低了犯错误的风险。crndm的编程模型由使用安全的持久指针和软件事务内存组成。

crndm接口的核心是三个指针包装器。开发者可以使用它们安全地分配持久内存。

  • Pbox<T>:最简单的动态分配形式,
  • Prc<T>:用于共享持久对象的单线程引用计数指针,
  • Parc<T>:用于共享持久对象的线程安全引用计数指针。

依赖项

crndm依赖于Rust的一些不稳定特性。因此,它需要一个nightly Rust编译器 1.50.0-nightly。请运行以下命令以下载最新的Rust版本(有关详细信息,请参阅https://www.rust-lang.net.cn/tools/install)。

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup default nightly

氧化铝也部分依赖于一些第三方crate,这些crate列在Cargo.toml中。

使用方法

使用以下任一指令将crndm添加到您的Cargo.toml依赖项部分

[dependencies]
crndm = { git = "https://github.com/NVSL/Corundum.git" }

或者(将在crates.io上提供,很快)

[dependencies]
crndm = "0.1.0"

内存池

内存池是一种实现了与持久内存工作所需的所有接口的类型。您可以使用默认的内存池,或者定义一个新的内存池类型。后者需要您的类型实现MemPool特质。请参考中继分配器作为示例。要自动实现新的池类型,提供了一个创建具有BuddyAlloc类型的模块的pool!()宏。

crndm::pool!(my_pool);

打开内存池文件

在使用之前,首先要打开内存池文件。您可以通过使用open()open_no_root()方法来完成此操作。第一个方法返回给定根对象类型的根对象。第二个方法返回一个guard对象;只要root/guard对象在作用域内,池就保持打开状态。打开函数接受池文件路径和创建池文件的标志。

if let Ok(_) = my_mod::BuddyAlloc::open_no_root("image", O_F) {
    println!("Image file is formatted and ready to use");
} else {
    println!("No image file found");
}
if let Ok(root) = my_mod::BuddyAlloc::open::<Root>("image", O_F) {
    println!("Image file is formatted and the root object is created ({:?})", root);
} else {
    println!("No image file");
}

PM安全数据结构

您可以使用给定的指针定义任何数据结构,而不需要任何原始指针或引用。氧化铝可以帮助您编写正确的代码。

use crndm::rc::Prc;
use crndm::cell::LogCell;

type A = BuddyAlloc;

struct MyData {
    id: i32,
    link: Option<Prc<LogRefCell<MyData, A>, A>>
}

您可能会发现,在每种类型中指定池会令人烦恼。氧化铝使用类型别名和过程宏提供了一种更简单的方式来定义新的数据结构。pool!()宏将所有与内部池类型关联的持久类型别名。例如

pool!(my_pool);
use my_pool::*;

struct MyData {
    id: i32,
    link: Option<Prc<PRefCell<MyData>>>
}

PCloneRoot过程宏也可以用来自动推导类型的相应特质的实现。

use crndm::default::*;

#[derive(PClone, Root)]
struct MyData {
    id: i32,
    link: Option<Prc<PRefCell<MyData>>>
}

事务性内存

crndm不允许在事务之外对受保护的数据进行任何修改。要允许可变借用受保护的数据,您可以将它包裹在LogCellMutex等中,并使用它们的相应接口进行内部可变性,这需要引用一个日志对象。要获取日志,您可以使用transaction

transaction(|j| {
    let my_data = Prc::new(LogRefCell::new(
        MyData {
            id: 1,
            link: None
        }), j);
    let mut my_data = my_data.borrow_mut(j);
    my_data.id = 2;
})

文档

请访问Documentation页面获取更多信息。

问题和贡献

请随时通过GitHub问题报告任何错误。

如果您有其他问题或建议,您可以联系[email protected]

许可证

'crndm' crate是在Apache License, Version 2.0(http://www.apache.org/licenses/LICENSE-2.0)下许可的。

除非您明确表示,否则您有意提交的任何贡献,包括您提交给许可人的工作,都应遵守本许可的条款和条件,而无需任何额外的条款或条件。

依赖项

~4.5–6MB
~117K SLoC