LearningOS / rust-based-os-comp2023

2023秋冬季开源操作系统训练营
https://github.com/LearningOS/rust-based-os-comp2023
GNU General Public License v3.0
2.13k stars 351 forks source link

lab1运行结果不对 #148

Open shiwenlong12 opened 1 year ago

shiwenlong12 commented 1 year ago

在TCB中加入syscall_times时运行结果[FAIL] not found <get_time OK13047! (\d+)>,在ch3b_sleep中get_time()得到的是0,无法通过测试,去掉syscall_times后其他的都通过了,只有[FAIL] not found ,ch3_taskinfo.rs无法比较syscall_times不能通过,之前有个一样的问题https://github.com/LearningOS/rust-based-os-comp2022/issues/95

有人回答说是因为TCB里面放一个500大小的数组太大了, 似乎是内存的问题, 你改成5就可以了. btw 似乎这样实现的性能比较低,但是如果改成大小为5的数组的话,ch3_taskinfo.rs 中assert_eq!(1, info.syscall_times[SYSCALL_TASK_INFO]);SYSCALL_TASK_INFO是410,还是不能通过。

idlercloud commented 1 year ago

wx 群里其实有过两次讨论这个问题。应该确实是数组过大的问题,导致启动栈溢出了 多给几种解决方案吧,优先度依次降低:

  1. 把 syscall_times 存在一个 Vec 中。因为 heap_alloc 中已经指定了 global_allocator,所以其实已经可以用堆了。
  2. entry.asm 里修改 boot_stack 的大小,本来应该是 4096*16,改成 4096*32 应该就可以。可能还需要把 Cargo.toml 里面的 opt-level=0 注释掉,启动较高等级的优化。
  3. ch3_taskinfo.rs 里需要返回值是 [u32;500],但你存在 TCB 中的可以是 [u32;5],只要在系统调用的那个地方填入相应的值,其它的填 0 就好了。
  4. Cargo.toml 里注释掉 opt-level=0,并添加 lto="fat" 开启链接时优化。
  5. 把 syscall_times 存在 TrapContext 或者 TaskContext 或者内核栈之类的地方,总之就是换个位置。
shiwenlong12 commented 1 year ago

好的,问题解决了,非常感谢。

CelestialMelody commented 1 year ago

wx 群里其实有过两次讨论这个问题。应该确实是数组过大的问题,导致启动栈溢出了 多给几种解决方案吧,优先度依次降低:

  1. 把 syscall_times 存在一个 Vec 中。因为 heap_alloc 中已经指定了 global_allocator,所以其实已经可以用堆了。
  2. entry.asm 里修改 boot_stack 的大小,本来应该是 4096*16,改成 4096*32 应该就可以。可能还需要把 Cargo.toml 里面的 opt-level=0 注释掉,启动较高等级的优化。
  3. ch3_taskinfo.rs 里需要返回值是 [u32;500],但你存在 TCB 中的可以是 [u32;5],只要在系统调用的那个地方填入相应的值,其它的填 0 就好了。
  4. Cargo.toml 里注释掉 opt-level=0,并添加 lto="fat" 开启链接时优化。
  5. 把 syscall_times 存在 TrapContext 或者 TaskContext 或者内核栈之类的地方,总之就是换个位置。

请问第一种解决方法该如何实现呢?

// #[derive(Copy, Clone)] // Vec can not derive(Copy)
#[derive(Clone)]
pub struct TaskControlBlock {
    pub task_status: TaskStatus,
    pub task_cx: TaskContext,

    // lab1
    // pub syscall_times: [u32; MAX_SYSCALL_NUM], // solve way: use vec
    pub syscall_times: Vec<u32>,
    pub first_run: bool,
    pub begin_time: usize,
    pub end_time: usize,
}

impl TaskControlBlock {
    pub fn new() -> Self {
        Self {
            task_cx: TaskContext::init(),
            task_status: TaskStatus::UnInit,

            syscall_times: Vec::with_capacity(MAX_SYSCALL_NUM),
            first_run: true,
            begin_time: 0,
            end_time: 0,
        }
    }
}

然而,在 lazy_static! 会报错: image

CelestialMelody commented 1 year ago

这里是因为,array 的元素要求实现 Copy Trait,而我们的 TCB 由于使用了 Vec,故无法 #[derive(Copy)];我们可以考虑,将tasks 也使用 Vec 实现,而不是使用数组。

补充

  1. array:重复表达式 [x; N],该数组生成包含 xN 副本的数组。 x 的类型必须为 [Copy]
  2. 为什么可以使用 Vec ? 标准库的 Vec 提供了 "a heap-allocated, reziable array type",但我们是在 #![no_std] 的条件下; 为什么能够使用?这是因为在 heap_alloc.rs 中,我们的 HEAP_ALLOCATOR 是 LockedHeap 类型,该类型已经实现了 alloc 库 中 GlobalAlloc 要求的抽象接口了, 并标注为 #[global_allocator]; Vec 构造时会调用 alloc 库提供的 allocate 函数,该函数又链接到带有 #[global_allocator] 标记的,实现了 GlobalAlloc Trait 的对象的同名方法,故可以使用。
Unik-lif commented 1 year ago

太感谢了!

yifeianyi commented 1 year ago

wx 群里其实有过两次讨论这个问题。应该确实是数组过大的问题,导致启动栈溢出了 多给几种解决方案吧,优先度依次降低:

  1. 把 syscall_times 存在一个 Vec 中。因为 heap_alloc 中已经指定了 global_allocator,所以其实已经可以用堆了。
  2. entry.asm 里修改 boot_stack 的大小,本来应该是 4096*16,改成 4096*32 应该就可以。可能还需要把 Cargo.toml 里面的 opt-level=0 注释掉,启动较高等级的优化。
  3. ch3_taskinfo.rs 里需要返回值是 [u32;500],但你存在 TCB 中的可以是 [u32;5],只要在系统调用的那个地方填入相应的值,其它的填 0 就好了。
  4. Cargo.toml 里注释掉 opt-level=0,并添加 lto="fat" 开启链接时优化。
  5. 把 syscall_times 存在 TrapContext 或者 TaskContext 或者内核栈之类的地方,总之就是换个位置。

大佬想请教下,是怎么debug 得出是启动栈溢出的结论的?有什么调试方法可以分享一下吗?