|
|
@ -1,8 +1,13 @@
|
|
|
|
//! App management syscalls
|
|
|
|
//! App management syscalls
|
|
|
|
|
|
|
|
use alloc::sync::Arc;
|
|
|
|
|
|
|
|
use crate::loader::get_app_data_by_name;
|
|
|
|
|
|
|
|
use crate::mm::page_table::{translated_refmut, translated_str};
|
|
|
|
// use crate::batch::run_next_app;
|
|
|
|
// use crate::batch::run_next_app;
|
|
|
|
use crate::println;
|
|
|
|
use crate::println;
|
|
|
|
use crate::task::{exit_current_and_run_next, suspend_current_and_run_next};
|
|
|
|
use crate::task::{exit_current_and_run_next, suspend_current_and_run_next};
|
|
|
|
use crate::task::processor::change_program_brk;
|
|
|
|
use crate::task::manager::add_task;
|
|
|
|
|
|
|
|
use crate::task::processor::{change_program_brk, current_task, current_user_token};
|
|
|
|
|
|
|
|
use crate::task::task::TaskStatus;
|
|
|
|
// use crate::task::{change_program_brk, exit_current_and_run_next, suspend_current_and_run_next};
|
|
|
|
// use crate::task::{change_program_brk, exit_current_and_run_next, suspend_current_and_run_next};
|
|
|
|
use crate::timer::get_time_ms;
|
|
|
|
use crate::timer::get_time_ms;
|
|
|
|
|
|
|
|
|
|
|
@ -30,3 +35,93 @@ pub fn sys_sbrk(size: i32) -> isize {
|
|
|
|
-1
|
|
|
|
-1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn sys_getpid() -> isize {
|
|
|
|
|
|
|
|
current_task().unwrap().pid.0 as isize
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn sys_fork() -> isize {
|
|
|
|
|
|
|
|
// 创建一个会 跳到trap_return的子进程
|
|
|
|
|
|
|
|
let current_task = current_task().unwrap();
|
|
|
|
|
|
|
|
let new_task = current_task.fork();
|
|
|
|
|
|
|
|
let new_pid = new_task.pid.0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 修改子进程 trap_context 中的返回值, 因为父进程在调用sys_call中之后会立即返回
|
|
|
|
|
|
|
|
let trap_cx = new_task.inner_exclusive_access().get_trap_cx();
|
|
|
|
|
|
|
|
// 我们之前 进入这个函数的时候, 已经对子进程的 结束陷入的进行返回的地址 +4了
|
|
|
|
|
|
|
|
// 所以现在只需要改变子进程 陷入之后的返回值即可, 将来子进程会直接从 trap_return运行
|
|
|
|
|
|
|
|
trap_cx.x[10] = 0;
|
|
|
|
|
|
|
|
// 添加子任务到全局的 任务管理器
|
|
|
|
|
|
|
|
add_task(new_task);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 返回 子进程的pid 给父进程
|
|
|
|
|
|
|
|
new_pid as isize
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 根据 文件名, 创建替换当前执行的任务
|
|
|
|
|
|
|
|
pub fn sys_exec(path: *const u8) -> isize {
|
|
|
|
|
|
|
|
// 当前token
|
|
|
|
|
|
|
|
let token = current_user_token();
|
|
|
|
|
|
|
|
// 得到 文件名
|
|
|
|
|
|
|
|
let path = translated_str(token, path);
|
|
|
|
|
|
|
|
// 根据文件名对应的二进制数据, 调用exec 替换
|
|
|
|
|
|
|
|
if let Some(data) = get_app_data_by_name(path.as_str()) {
|
|
|
|
|
|
|
|
let task = current_task().unwrap();
|
|
|
|
|
|
|
|
task.exec(data);
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// 不存在 返回-1
|
|
|
|
|
|
|
|
-1
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
|
|
|
|
|
|
|
|
// 当前进程 这里是父进程
|
|
|
|
|
|
|
|
let task = current_task().unwrap();
|
|
|
|
|
|
|
|
// find a child process
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果当前进程内没有对应pid的子进程 则返回-1, 如果传进来的pid是-1, 则表示任何一个子进程都是符合要求的
|
|
|
|
|
|
|
|
let mut inner = task.inner_exclusive_access();
|
|
|
|
|
|
|
|
if !inner
|
|
|
|
|
|
|
|
.children
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.any(|p| pid == -1 || pid as usize == p.get_pid())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
// ---- release current PCB
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 找到 指定进程且进程为 僵尸进程或者是任意进程
|
|
|
|
|
|
|
|
let pair = inner.children.iter().enumerate().find(|(_, p)| {
|
|
|
|
|
|
|
|
// ++++ temporarily access child PCB lock exclusively
|
|
|
|
|
|
|
|
p.inner_exclusive_access().task_status == TaskStatus::Zombie && (pid == -1 || pid as usize == p.get_pid())
|
|
|
|
|
|
|
|
// ++++ release child PCB
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果找到
|
|
|
|
|
|
|
|
if let Some((idx, _)) = pair {
|
|
|
|
|
|
|
|
// 从子列表中删除并取出
|
|
|
|
|
|
|
|
let child = inner.children.remove(idx);
|
|
|
|
|
|
|
|
// confirm that child will be deallocated after removing from children list
|
|
|
|
|
|
|
|
// 保证chlid当前是唯一存在的引用, 而不会出现在某个进程的子进程向量中, 更不会出现在处理器监控器或者任务管理器中, child在当前作用于结束后引用计数为0, 彻底删除,
|
|
|
|
|
|
|
|
// 作用域结束后, 内部的pid 和kernel stack 执行他们自己的drop方法(返还pid给pid管理器, 返还kernel stack的资源还给 KERNEL_SPACE, ), 还有 inner->memory_set->page_table->frames 三级页表本身所占的物理帧
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(Arc::strong_count(&child), 1);
|
|
|
|
|
|
|
|
let found_pid = child.get_pid();
|
|
|
|
|
|
|
|
// ++++ temporarily access child TCB exclusively
|
|
|
|
|
|
|
|
// 找到子进程的退出码
|
|
|
|
|
|
|
|
let exit_code = child.inner_exclusive_access().exit_code;
|
|
|
|
|
|
|
|
// ++++ release child PCB
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 将退出码, 写入到当前进程的地址空间
|
|
|
|
|
|
|
|
let exit_code_ref = translated_refmut(inner.memory_set.token(), exit_code_ptr);
|
|
|
|
|
|
|
|
*exit_code_ref = exit_code;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 返回回收的子进程的pid
|
|
|
|
|
|
|
|
found_pid as isize
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// 如果制定进程不是僵尸进程 返回-2, 上层用户应用调用的 wait pid 会继续等待
|
|
|
|
|
|
|
|
-2
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---- release current PCB lock automatically
|
|
|
|
|
|
|
|
}
|