rCore-Tutorial-Book-v3
rCore-Tutorial-Book-v3 copied to clipboard
rCore-Tutorial-Book-v3/chapter3/1multi-loader
多道程序放置与加载 — rCore-Tutorial-Book-v3 0.1 文档
https://rcore-os.github.io/rCore-Tutorial-Book-v3/chapter3/1multi-loader.html
我在切换到ch3-coop的时候(ch3之后的应该都会有),多了一个toolchain文件,其中设置rust 工具链版本为nightly-2022-01-19,是文件夹目录下的override,会导致rust-analyzer报错 具体是执行cargo之后出现: error: the 'cargo' binary, normally provided by the 'cargo' component, is not applicable to the 'nightly-2022-01-19-x86_64-unknown-linux-gnu' toolchain 执行rustup upgrade,并执行rustup component remove cargo、rustup component add cargo之后可解决
尝试着改造自己的内核成多道程序加载执行,然后对于最后的执行,把用户栈改造成多个栈供用户程序使用,然后run_next_app关于restore程序传入,改造成如下代码
__restore(
KERNEL_STACK.push_context(TrapContext::app_init_context(
APP_BASE_ADDRESS + current_app * APP_SIZE_LIMIT,
USER_STACK[current_app].get_sp(),
)) as *const _ as usize,
);
然后执行到第二个程序就开始报错
Loaded app 0 within 0x80400000 to 0x804014B0
Loaded app 1 within 0x80420000 to 0x80421558
Loaded app 2 within 0x80440000 to 0x80441720
Loaded app 3 within 0x80460000 to 0x80461540
Loaded app 4 within 0x80480000 to 0x80481AD8
Loaded app 5 within 0x804A0000 to 0x804A1BC0
[kernel] Running app_0
Entry: 0x80400000
UserStack: 0x80207000
syswrite buf: 0x80400F28
Hello, world!
[kernel] Application exited with code 0
[kernel] Running app_1
Entry: 0x80420000
UserStack: 0x80208000
syswrite buf: 0x80207F30
Panicked at src/syscall/fs.rs:15 called `Result::unwrap()` on an `Err` value: Utf8Error { valid_up_to: 3, error_len: Some(1) }
完全不知道哪里出了问题...
本来以为我解决了这个问题,没想到最后还是没解决... 麻了,我跟上面这位老哥基本是以相同的方式操作的,只不过我的源程序是模块化的,所以说比较怪异 输出:
[ INFO] [kernel] num_app = 12
[ INFO] All application has been linked at this location( in memory )
[ INFO] [kernel] app_0 [0x80400000, 0x80420000)
[ INFO] [kernel] app_1 [0x80420000, 0x80440000)
[ INFO] [kernel] app_2 [0x80440000, 0x80460000)
[ INFO] [kernel] app_3 [0x80460000, 0x80480000)
[ INFO] [kernel] app_4 [0x80480000, 0x804a0000)
[ INFO] [kernel] app_5 [0x804a0000, 0x804c0000)
[ INFO] [kernel] app_6 [0x804c0000, 0x804e0000)
[ INFO] [kernel] app_7 [0x804e0000, 0x80500000)
[ INFO] [kernel] app_8 [0x80500000, 0x80520000)
[ INFO] [kernel] app_9 [0x80520000, 0x80540000)
[ INFO] [kernel] app_10 [0x80540000, 0x80560000)
[ INFO] [kernel] app_11 [0x80560000, 0x8026d6a8)
[DEBUG] KERNEL_STACK:8020D000
[DEBUG] USER_STACK:8020E000
[DEBUG] you are now loading application:1
[DEBUG] restore to address in :80400000
[DEBUG] USER_STACK.get_sp:8020E000
Hello, world!
[ INFO] [kernel] Application exited with code 0
[DEBUG] you are now loading application:2
[DEBUG] restore to address in :80420000
[DEBUG] USER_STACK.get_sp:8020E000
[ERROR] [kernel] IllegalInstruction in application, core dumped.
[ INFO] exit and run next application:
[DEBUG] you are now loading application:3
[DEBUG] restore to address in :80440000
[DEBUG] USER_STACK.get_sp:8020E000
[ERROR] unsupported trap
Panicked at trap/src/lib.rs:53 Unsupported trap Exception(LoadFault), stval = 0x0!
其他乱七八糟的东西
pub fn run_next_app() -> ! {
let mut app_manager = APP_MANAGER.exclusive_access();
let current_app = app_manager.get_current_app();
if current_app == app_manager.num_app {
// debug!("inside");
panic!("all application has been run successed");
}
// copy app instruction to APP_BASR_ADDRESS
app_manager.set_current_app(current_app + 1);
let next_app_num = current_app + 1;
let next_ptr = app_manager.app_start[current_app];
drop(app_manager);
// before this we have to drop local variables related to resources manually
// and release the resources
debug!("you are now loading application:{}",next_app_num);
debug!("restore to address in :{:x}", next_ptr);
debug!("USER_STACK.get_sp:{:X}", USER_STACK.get_sp());
extern "C" {
fn __restore(cx_addr: usize);
}
unsafe {
// push TrapContext into kernelStack
__restore(KERNEL_STACK.push_context(TrapContext::app_init_context(
next_ptr,
USER_STACK.get_sp(),
)) as *const _ as usize)
}
panic!("Unreachable in batch::run_current_app!");
}
lazy_static! {
// UPSafeCell: prevent multi borrows
static ref APP_MANAGER: UPSafeCell<AppManager> = unsafe {
UPSafeCell::new({
extern "C" {
// static mut _num_app: u64;
fn _num_app();
}
// get _num_app
let num_app_ptr = _num_app as usize as *const usize;
// read number of "should run" apps
let num_app = num_app_ptr.read_volatile();
// array stores the start address of app
let mut app_start: [usize; MAX_APP_NUM + 1] = [0; MAX_APP_NUM + 1];
// read address of app from _num_app, should from [1..?]
let app_start_raw: &[usize] =
core::slice::from_raw_parts(num_app_ptr.add(1), num_app + 1);
// app_start[0..num_app] stores app start addresses
app_start[..=num_app].copy_from_slice(app_start_raw);
// before this line we have successed load all application in the location of app_start
// and all application has been load in the address start from 0x80218790?
// so we just load it in the address from 0x8400000
// core::arch::asm!("fence.i");
// load application in memory
for i in 0..num_app {
let base_i = APP_BASE_ADDRESS + i * APP_SIZE_LIMIT;
// the app_start[i] here is stand for the location where they has been load in memeory now
loader::load_app(app_start[i], app_start[i+1], base_i);// 将app_start[i]~app_start[i+1]的内容装载到base_i的位置上
// update app_start
app_start[i] = base_i;
}
// store infos into AppManager
AppManager {
num_app,
current_app: 0,
app_start,
}
})
};
}
docs error: 最后一段执行应用程序处,应为sepc
而非epc
寄存器
@SnowWarri0r @jackyliu16 我也有这个问题,后来发现是我的user程序的起始地址有问题,以前是固定的0x80400000,而这一章需要是不同的地址。我不知道你们是不是这个问题。
@SnowWarri0r @jackyliu16 我也有这个问题,后来发现是我的user程序的起始地址有问题,以前是固定的0x80400000,而这一章需要是不同的地址。我不知道你们是不是这个问题。
我想应该不是这个原因,写的时候我人工deprecated
了原先版本中由APP_MANAGER
提供的load_app(i)
函数,并且将原先的这个load
模块中与APP_BASE_ADDRESS
相关的内容全部替换成为了APP_BASE_ADDRESS+app_id * APP_SIZE_LIMIT
的这种类型的操作,并且通过extern "C" { fn _num_app(); }
在初始化阶段完成了对应程序的装载操作,除了我仍使用原来提供的__restore
函数来达成切换当前正在运行的程序以外,我似乎没有任何有关于引起程序没有办法正常加载的想法。
@SnowWarri0r @jackyliu16 使用cargo clean清理user程序,然后使用build.py重新编译生成user程序。cargo build 貌似不会跟踪ld文件改动。
与第二章相同,所有应用的 ELF 格式执行文件都经过 objcopy 工具丢掉所有 ELF header 和符号变为二进制镜像文件,随后以同样的格式通过在操作系统内核中嵌入 link_user.S 文件,在编译时直接把应用链接到内核的数据段中。
多道程序放置一节中此处的link_user.S是否应为link_app.S?