3个版本 (重大更新)

0.3.0 2023年10月19日
0.2.0 2022年10月27日
0.1.0 2022年7月28日

#1284 in 过程宏


nt-list 中使用

MIT/Apache

9KB
178

nt-list

crates.io docs.rs license: MIT OR Apache-2.0

作者:Colin Finck <[email protected]>

提供了兼容的、类型安全的和惯用的Rust实现,用于Windows NT链接列表,称为LIST_ENTRYSINGLE_LIST_ENTRY

应用实例


在WinDbg中调试Rust应用程序并使用!list扩展遍历双向链表。这是nt-list和LIST_ENTRY之间兼容性的证明。

详细信息

此格式的单链表和双链表是Windows本身和为Windows编写的驱动程序中广泛使用的基层数据结构。对于双链表,Windows定义了一个具有指向其他LIST_ENTRY结构的正向和反向指针的LIST_ENTRY结构。然后将LIST_ENTRY嵌入到您自己的元素结构中。有关Windows中链表更详细的信息,请参阅相关微软文档

此设计表现出一些与教科书中的链表实现不同的特性

  • 单个元素可以属于多个列表(通过具有多个LIST_ENTRY字段)。
  • 您负责将同一类型的元素推送到列表中。没有类型安全性,C/C++编译器无法阻止您将不同类型的元素添加到同一列表中。
  • 链接指向元素中的LIST_ENTRY字段,而不是元素本身。您需要使用CONTAINING_RECORD检索相应的元素结构,并且您需要对传递给该宏的所有参数负责。

nt-list存储库引入了这些列表的类型安全性,将一些责任从用户移到编译器。此外,它提供了一个类似于LinkedListVec的Rust接口。

示例

使用nt-list创建链表简化为以下三个步骤

  1. 您定义一个空枚举来标识您的列表(在推送元素时提供类型安全性),并推导出NtList(双向链表)或NtSingleList(单向链表)。
  2. 您定义元素结构,如果需要,声明一个条目为#[boxed],并推导出NtListElement
  3. 您使用元素结构和空枚举作为类型参数调用相应列表实现中的new

所有这些加在一起看起来像

#[derive(NtSingleList)]
enum MyList {}

#[derive(Default, NtListElement)]
#[repr(C)]
struct MyElement {
    #[boxed]
    entry: NtSingleListEntry<Self, MyList>,
    value: i32,
}

fn test() {
    let mut list = NtBoxingSingleListHead::<MyElement, MyList>::new();

    list.push_back(MyElement {
        value: 42,
        ..Default::default()
    });

    for element in list.iter() {
        println!("{}", element.value);
    }
}

有关双向链表的示例,请参阅list模块级别的文档

no_std支持

此存储库与no_std兼容,因此可以从固件级代码到用户模式应用程序使用。

为了在NtBoxingListHeadNtBoxingSingleListHead中支持堆分配,此存储库依赖于alloc库。如果您想在没有堆分配的纯no_std环境中使用此存储库,请使用default-features = false包含它以禁用默认的alloc功能。

许可

此存储库受以下任一许可的许可:

任选。

除非您明确声明,否则您提交的任何有意包含在作品中的贡献,如Apache-2.0许可证中定义的,将按照上述方式双许可,没有任何附加条款或条件。

依赖项

~280–730KB
~17K SLoC