以下说的都是 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 相互持有对方引用,造成死锁,无法释放实例。