4个版本 (2个破坏性更新)
0.3.0 | 2023年10月19日 |
---|---|
0.2.1 | 2023年10月19日 |
0.2.0 | 2022年10月27日 |
0.1.0 | 2022年7月28日 |
#301 在 Windows APIs
84KB
1K SLoC
nt-list
由 Colin Finck <[email protected]>
提供兼容的、类型安全的、符合Rust语法的Windows NT链接列表实现,称为LIST_ENTRY
和SINGLE_LIST_ENTRY
。
行动中的示例
在WinDbg中调试Rust应用程序并使用!list
扩展遍历双链表。这是nt-list
和LIST_ENTRY
之间兼容性的证明。
详细信息
这种格式的单链表和双链表是Windows自身以及为Windows编写的驱动程序中广泛使用的根本性数据结构。在双链表的情况下,Windows定义了一个包含指向其他LIST_ENTRY
结构的正向和反向指针的LIST_ENTRY
结构。然后LIST_ENTRY
被嵌入到您的自己的元素结构中。有关Windows中链接列表的更多详细信息,请参阅相关Microsoft文档。
此设计具有与教科书中的链接列表实现不同的几个特性
- 单个元素可以属于多个列表(通过具有多个
LIST_ENTRY
字段)。 - 您负责只将同一类型的元素推送到列表中。没有类型安全性,C/C++编译器无法阻止您将不同类型的元素添加到同一列表中。
- 链接指向元素中的
LIST_ENTRY
字段,而不是指向元素本身。您需要使用CONTAINING_RECORD
来检索相应的元素结构,并且您负责传递给该宏的所有参数。
nt-list crate 为这些列表引入了类型安全,将一些责任从用户转移到编译器。此外,它提供了一个类似于 LinkedList
和 Vec
的 Rust 接口。
示例
使用 nt-list
创建链表归结为以下三个步骤
- 您定义一个空的枚举来标识您的列表(在推送元素时保证类型安全),并派生
NtList
(双向链表)或NtSingleList
(单向链表)。 - 您定义您的元素结构,声明一个条目作为
#[boxed]
(如果需要),并派生NtListElement
。 - 您使用元素结构和空枚举作为类型参数,调用相应列表实现的
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
支持
该 crate 与 no_std
兼容,因此可以从固件级别的代码到用户模式应用程序使用。
为了在 NtBoxingListHead
和 NtBoxingSingleListHead
中支持堆分配,该 crate 依赖于 alloc
库。如果您想在纯 no_std
环境中使用该 crate 而不进行堆分配,请使用 default-features = false
包含它以禁用默认的 alloc
功能。
许可协议
此 crate 可在以下任一项许可协议下使用:
任选其一。
除非您明确表示,否则,您故意提交以包含在您的工作中的任何贡献,根据 Apache-2.0 许可协议定义,应如上所述双许可,不附加任何额外条款或条件。
依赖项
~340–780KB
~18K SLoC