lab1运行结果不对
在TCB中加入syscall_times时运行结果[FAIL] not found <get_time OK13047! (\d+)>,在ch3b_sleep中get_time()得到的是0,无法通过测试,去掉syscall_times后其他的都通过了,只有[FAIL] not found
有人回答说是因为TCB里面放一个500大小的数组太大了, 似乎是内存的问题, 你改成5就可以了. btw 似乎这样实现的性能比较低,但是如果改成大小为5的数组的话,ch3_taskinfo.rs 中assert_eq!(1, info.syscall_times[SYSCALL_TASK_INFO]);SYSCALL_TASK_INFO是410,还是不能通过。
wx 群里其实有过两次讨论这个问题。应该确实是数组过大的问题,导致启动栈溢出了 多给几种解决方案吧,优先度依次降低:
- 把 syscall_times 存在一个
Vec中。因为heap_alloc中已经指定了global_allocator,所以其实已经可以用堆了。 - 在
entry.asm里修改boot_stack的大小,本来应该是4096*16,改成4096*32应该就可以。可能还需要把Cargo.toml里面的opt-level=0注释掉,启动较高等级的优化。 ch3_taskinfo.rs里需要返回值是[u32;500],但你存在 TCB 中的可以是[u32;5],只要在系统调用的那个地方填入相应的值,其它的填 0 就好了。- 在
Cargo.toml里注释掉opt-level=0,并添加lto="fat"开启链接时优化。 - 把 syscall_times 存在 TrapContext 或者 TaskContext 或者内核栈之类的地方,总之就是换个位置。
好的,问题解决了,非常感谢。
wx 群里其实有过两次讨论这个问题。应该确实是数组过大的问题,导致启动栈溢出了 多给几种解决方案吧,优先度依次降低:
- 把 syscall_times 存在一个
Vec中。因为heap_alloc中已经指定了global_allocator,所以其实已经可以用堆了。- 在
entry.asm里修改boot_stack的大小,本来应该是4096*16,改成4096*32应该就可以。可能还需要把Cargo.toml里面的opt-level=0注释掉,启动较高等级的优化。ch3_taskinfo.rs里需要返回值是[u32;500],但你存在 TCB 中的可以是[u32;5],只要在系统调用的那个地方填入相应的值,其它的填 0 就好了。- 在
Cargo.toml里注释掉opt-level=0,并添加lto="fat"开启链接时优化。- 把 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! 会报错:

这里是因为,array 的元素要求实现 Copy Trait,而我们的 TCB 由于使用了 Vec,故无法 #[derive(Copy)];我们可以考虑,将tasks 也使用 Vec 实现,而不是使用数组。
补充
- array:重复表达式
[x; N],该数组生成包含x的N副本的数组。x的类型必须为[Copy]。- 为什么可以使用 Vec ? 标准库的 Vec <T> 提供了 "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 的对象的同名方法,故可以使用。
太感谢了!
wx 群里其实有过两次讨论这个问题。应该确实是数组过大的问题,导致启动栈溢出了 多给几种解决方案吧,优先度依次降低:
- 把 syscall_times 存在一个
Vec中。因为heap_alloc中已经指定了global_allocator,所以其实已经可以用堆了。- 在
entry.asm里修改boot_stack的大小,本来应该是4096*16,改成4096*32应该就可以。可能还需要把Cargo.toml里面的opt-level=0注释掉,启动较高等级的优化。ch3_taskinfo.rs里需要返回值是[u32;500],但你存在 TCB 中的可以是[u32;5],只要在系统调用的那个地方填入相应的值,其它的填 0 就好了。- 在
Cargo.toml里注释掉opt-level=0,并添加lto="fat"开启链接时优化。- 把 syscall_times 存在 TrapContext 或者 TaskContext 或者内核栈之类的地方,总之就是换个位置。
大佬想请教下,是怎么debug 得出是启动栈溢出的结论的?有什么调试方法可以分享一下吗?