Skip to content

ch5 TaskControlBlock::exec should initialize program_brk and heap_bottom #161

@billlosw

Description

@billlosw

在当前实现中, TaskControlBlock::exec 只有更新子进程的 inner.base_size = user_sp;, 并无更新 heap_bottomprogram_brk .

考虑一种情况, 如果我的父进程 f 使用了不少的 heap 空间, 这时候他现在尝试 fork+exec 弄一个子进程 s.

首先在 fork 的时候, 子进程完全复制了一份父进程的 heap 空间的内容(brk, heap_bottom, heap上的数据).

然后子进程调用 exec, 把他的 inner 的 memory_setfrom_elf() 的东西替换掉. 这时候原 memory_set, 即来自父进程的 heap 空间上的数据被释放了. 之后再把子进程自己 inner 中的 trap_cx_ppnbase_size 更新.

MemorySet::from_elf() 的实现可以看到, 他的 heap 空间已经是空的, 没有实际映射任何虚拟或者物理页.

pub fn from_elf(elf_data: &[u8]) -> (Self, usize, usize) {
    ...
    // map user stack with U flags
    memory_set.push(
        MapArea::new_with_va(
            user_stack_bottom.into(),
            user_stack_top.into(),
            MapType::Framed,
            MapPermission::R | MapPermission::W | MapPermission::U,
        ),
        None,
    );
    // used in sbrk
    memory_set.push(
        MapArea::new_with_va(
            user_stack_top.into(),
            user_stack_top.into(),
            MapType::Framed,
            MapPermission::R | MapPermission::W | MapPermission::U,
        ),
        None,
    );
    // map TrapContext
   ...
}

然而这时候子进程 inner 中的 brk, heap_bottom 依旧是使用的父进程的 brk 和 bottom. 但 memory_set 中现在并无对应的 heap 数据物理页. 此时若对这个子进程用 change_program_brk() 之类的函数, 会出现一些未定义行为.

因此我认为在 TaskControlBlock::exec() 中应该需要添加上:

...
// substitute memory_set
inner.memory_set = memory_set;
// update trap_cx ppn
inner.trap_cx_ppn = trap_cx_ppn;
// initialize base_size
inner.base_size = user_sp;
// initialize heap info
+ inner.heap_bottom = user_sp;
+ inner.program_brk = user_sp;
..

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions