3个版本 (重大更新)
0.3.0 | 2023年10月19日 |
---|---|
0.2.0 | 2022年10月27日 |
0.1.0 | 2022年7月28日 |
#1284 in 过程宏
在 nt-list 中使用
9KB
178 行
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中链表更详细的信息,请参阅相关微软文档。
此设计表现出一些与教科书中的链表实现不同的特性
- 单个元素可以属于多个列表(通过具有多个
LIST_ENTRY
字段)。 - 您负责将同一类型的元素推送到列表中。没有类型安全性,C/C++编译器无法阻止您将不同类型的元素添加到同一列表中。
- 链接指向元素中的
LIST_ENTRY
字段,而不是元素本身。您需要使用CONTAINING_RECORD
检索相应的元素结构,并且您需要对传递给该宏的所有参数负责。
nt-list存储库引入了这些列表的类型安全性,将一些责任从用户移到编译器。此外,它提供了一个类似于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
支持
此存储库与no_std
兼容,因此可以从固件级代码到用户模式应用程序使用。
为了在NtBoxingListHead
和NtBoxingSingleListHead
中支持堆分配,此存储库依赖于alloc
库。如果您想在没有堆分配的纯no_std
环境中使用此存储库,请使用default-features = false
包含它以禁用默认的alloc
功能。
许可
此存储库受以下任一许可的许可:
任选。
除非您明确声明,否则您提交的任何有意包含在作品中的贡献,如Apache-2.0许可证中定义的,将按照上述方式双许可,没有任何附加条款或条件。
依赖项
~280–730KB
~17K SLoC