Open shiwenlong12 opened 1 year ago
wx 群里其实有过两次讨论这个问题。应该确实是数组过大的问题,导致启动栈溢出了 多给几种解决方案吧,优先度依次降低:
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"
开启链接时优化。好的,问题解决了,非常感谢。
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
提供了 "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 得出是启动栈溢出的结论的?有什么调试方法可以分享一下吗?
在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,还是不能通过。