例如,假设我有一个PageTable的值,并用CR3寄存器注册它的物理地址.

#![no_std]

use {
    spinning_top::{const_spinlock, Spinlock},
    x86_64::structures::paging::PageTable,
};

// The physical address of `PML4` is registered with CR3 register.
static PML4: Spinlock<PageTable> = const_spinlock(PageTable::new());

如果一个页面被访问,处理器将更改条目PML4的访问位.我担心优化后的代码可能会使用存储在CPU寄存器或堆栈中的缓存值,而不是内存中的实际值,从而导致使用位的旧值.

在这种情况下,影响应该很小,我不在乎访问的位.但是,一般来说,处理器可能意外更改的值(如MMIO和DMA缓冲区)或对该值的引用是否安全?或者我应该每次通过read_volatilewrite_volatile的原始指针执行读-修改-写循环吗?

推荐答案

由于您特别询问了"对这样一个值的引用":如果您有一个&T,而T在引用存在时由于any个原因发生了变异,那么程序will将显示未定义的行为.

据我所知,参考文献中的文件在这一点上还不是最终的,但原则是明确的.从UnsafeCell份文件中:

如果你有推荐人&;T、 然后通常在编译器中

和(长度编辑):

如果您创建了一个生命周期为"a"(a&;T或&;T)的安全引用

实际上,如果有&PML4&mut PML4PML4的"挥发性"属性可以被认为是通过"隐藏"别名的Mutations .

根据您的需要,您需要通过read_volatile(这是安全的,因为read_volatile always将底层内存的副本复制到不可变内存中)来 bootstrap 对PML4的访问;然后,你可以自由地给出该副本的参考资料.或者把它包装成UnsafeCell<PML4>,在这种情况下,仍然需要通过读取内部指针的值(不稳定或不稳定)来进行访问,但至少可以传递&UnsafeCell<PML4>.

Rust相关问答推荐

即使参数和结果具有相同类型,fn的TypId也会不同

何时可以在Rust中退出异步操作?

如何将`Join_all``Vec<;Result<;Vec<;Foo&>;,Anywhere::Error&>;`合并到`Result<;Vec<;Foo&>;,Anywhere::Error&>;`

在UdpSocket上使用sendto时的隐式套接字绑定

在Rust 中移动原始指针的靶子安全吗

在铁 rust 中,如何一次只引用几件事中的一件?

如何使用reqwest进行异步请求?

为什么我需要 to_string 函数的参考?

仅发布工作区的二进制 crate

Rust Option 的空显式泛型参数

我们可以在 Rust 切片中使用步骤吗?

在描述棋盘时如何最好地使用特征与枚举

在运行时在 Rust 中加载字体

从现有系列和 map 值创建新系列

LinkedList::drain_filter::drop 中 DropGuard 的作用是什么?

为什么1..=100返回一个范围而不是一个整数?

为什么 Rust 编译器在移动不可变值时执行复制?

带有库+多个二进制文件的Cargo 项目,二进制文件由多个文件组成?

Rust:为什么在 struct 中borrow 引用会borrow 整个 struct?

来自外部函数的future 内部可变引用