以下说的都是 std::sync
下的。
下面是一个进程控制块的实现,可以发现,当前进程使用 Weak<T>
指向父进程,使用 Arc<T>
指向子进程
os/src/task/task.rs 12:
pub struct TaskControlBlock {
// immutable
pub pid: PidHandle,
pub kernel_stack: KernelStack,
// mutable
inner: UPSafeCell<TaskControlBlockInner>,
}
pub struct TaskControlBlockInner {
pub trap_cx_ppn: PhysPageNum,
pub base_size: usize,
pub task_cx: TaskContext,
pub task_status: TaskStatus,
pub memory_set: MemorySet,
pub parent: Option<Weak<TaskControlBlock>>,
pub children: Vec<Arc<TaskControlBlock>>,
pub exit_code: i32,
}
首先说 Arc,实际上就是 Atomic RC,即原子引用计数,主要是为了并发安全。
Rust 严格要求:每个值都有唯一所有者,且值随所有者离开作用域而销毁。
而弱引用是为了处理一些特殊情况,如循环引用、双向引用而存在的。弱引用使得能够持有某对象的引用,却又不必成为此对象的所有者。
对于一个引用计数的实例,其内部分为 弱引用 和 强引用 两部分。通过 Weak<T>
持有引用,会导致 Arc 实例的弱引用计数加 1,而实例的释放无关弱引用,只要强引用数为 0,就会释放实例。
从而,避免了 Parent 持有 Children 相互持有对方引用,造成死锁,无法释放实例。