mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 08:06:32 +00:00
进程管理模块重构完成 (#380)
* 添加新版pcb的数据结构 (#273) * 将pcb中的内容分类,分别加锁 (#305) * 进程管理重构:完成fork的主体逻辑 (#309) 1.完成fork的主体逻辑 2.将文件系统接到新的pcb上 3.经过思考,暂时弃用signal机制,待进程管理重构完成后,重写signal机制.原因是原本的signal机制太烂了 * chdir getcwd pid pgid ppid (#310) --------- Co-authored-by: longjin <longjin@RinGoTek.cn> * 删除旧的fork以及signal的代码,并调整fork/vfork/execve系统调用 (#325) 1.删除旧的fork 2.删除signal相关代码,等进程管理重构结束之后,再重新写. 3.调整了fork/vfork/execve系统调用 * 实现切换进程的代码 (#331) * 实现切换进程的代码 * Patch modify preempt (#332) * 修改设置preempt的代码 * 删除rust的list和refcount * 为每个核心初始化idle进程 (#333) * 为每个核心初始化idle进程 * 完成了新的内核线程机制 (#335) * 调度器的pcb替换为新的Arc<ProcessControlBlock>,把调度器队列锁从 RwSpinLock 替换为了 SpinLock (#336) * 把调度器的pcb替换为新的Arc<ProcessControlBlock> * 把调度器队列锁从 RwSpinLock 替换为了 SpinLock ,修改了签名以通过编译 * 修正一些双重加锁、细节问题 --------- Co-authored-by: longjin <longjin@RinGoTek.cn> * github workflow自动检查代码是否格式化 * cache toolchain yml * 调整rust版本的waitqueue中的pcb为新版的pcb (#343) * 解决设置rust workspace带来的“工具链不一致”的问题 (#344) * 解决设置rust workspace带来的“工具链不一致”的问题 更改workflow * 调整pcb的sched_info和rwlock,以避免调度器死锁问题 (#341) * 调整pcb的sched_info和rwlock,以避免调度器死锁问题 * 修改为在 WriterGuard 中维护 Irq_guard * 修正了 write_irqsave方法 * 优化了代码 * 把 set state 操作从 wakup 移动到 sched_enqueue 中 * 修正为在 wakeup 中设置 running ,以保留 set_state 的私有性 * 移除了 process_wakeup * 实现进程退出的逻辑 (#340) 实现进程退出的逻辑 * 标志进程sleep * 修复wakeup的问题 --------- Co-authored-by: longjin <longjin@RinGoTek.cn> * rust 重构 completion (#350) * 完成了completion的基本结构,待完善上级调用 * 用SpinLock保护结构体并发安全 * 修改原子变量为u32,修复符号错误 * irq guard * 修改为具有内部可变性的结构体 * temp fix * 修复了由于进程持有自旋锁导致的不被调度的问题 * 对 complete 系列方法上锁,保护 done 数据并发安全 * 移除了未使用的依赖 * 重写显示刷新驱动 (#363) * 重构显示刷新驱动 * Patch refactor process management (#366) * 维护进程树 * 维护进程树 * 更改代码结构 * 新建进程时,设置cwd * 调整adopt childern函数,降低开销 --------- Co-authored-by: longjin <longjin@RinGoTek.cn> * waitqueue兼容C部分 (#351) * PATH * safe init * waitqueue兼容C部分 * waitqueue兼容C部分 * 删除semaphore.c,在ps2_keyboard中使用waitqueue * 删除semaphore.c,在ps2_keyboard中使用waitqueue * current_pcb的C兼容 * current_pcb的C兼容 * current_pcb的C兼容 * fmt * current_pcb的兼容 * 针对修改 * 调整代码 * fmt * 删除pcb的set flags * 更改函数名 --------- Co-authored-by: longjin <longjin@RinGoTek.cn> * merge master * Patch debug process management refactor (#372) * 能够调通,执行完textui_init * 能跑到initial kernel thread * fmt * 能够正常初始化所有服务(尚未能切换到用户程序) * 删除部分无用的extern * 存在问题:ap处理器启动后,bsp的smp_init函数return之后就出错了,怀疑是栈损坏 * 解决smp启动由于未换栈导致的内存访问错误 * debug * 1 * 1 * lock no preempt * 调通 * 优化代码,删除一些调试日志 * fix * 使用rust重写wait4 (#377) * 维护进程树 * 维护进程树 * 更改代码结构 * 新建进程时,设置cwd * 调整adopt childern函数,降低开销 * wait4 * 删除c_sys_wait4 * 使用userbuffer保护裸指针 --------- Co-authored-by: longjin <longjin@RinGoTek.cn> * 消除warning * 1. 修正未设置cpu executing的问题 * 修正kthread机制可能存在的内存泄露问题 * 删除pcb文档 * 删除C的tss struct --------- Co-authored-by: Bullet <93781792+GP-Bullet@users.noreply.github.com> Co-authored-by: Chiichen <39649411+Chiichen@users.noreply.github.com> Co-authored-by: hanjiezhou <zhouhanjie@dragonos.org> Co-authored-by: GnoCiYeH <118462160+GnoCiYeH@users.noreply.github.com> Co-authored-by: houmkh <1119644616@qq.com>
This commit is contained in:
@ -6,7 +6,7 @@ use core::{
|
||||
use num_traits::{FromPrimitive, ToPrimitive};
|
||||
|
||||
use crate::{
|
||||
arch::{cpu::cpu_reset, MMArch},
|
||||
arch::{cpu::cpu_reset, interrupt::TrapFrame, MMArch},
|
||||
driver::base::block::SeekFrom,
|
||||
filesystem::vfs::{
|
||||
fcntl::FcntlCommand,
|
||||
@ -14,11 +14,12 @@ use crate::{
|
||||
syscall::{PosixKstat, SEEK_CUR, SEEK_END, SEEK_MAX, SEEK_SET},
|
||||
MAX_PATHLEN,
|
||||
},
|
||||
include::bindings::bindings::{pid_t, PAGE_2M_SIZE, PAGE_4K_SIZE},
|
||||
include::bindings::bindings::{PAGE_2M_SIZE, PAGE_4K_SIZE},
|
||||
kinfo,
|
||||
libs::align::page_align_up,
|
||||
mm::{verify_area, MemoryManagementArch, VirtAddr},
|
||||
net::syscall::SockAddr,
|
||||
process::Pid,
|
||||
time::{
|
||||
syscall::{PosixTimeZone, PosixTimeval},
|
||||
TimeSpec,
|
||||
@ -368,11 +369,8 @@ pub const SYS_MUNMAP: usize = 45;
|
||||
|
||||
pub const SYS_MPROTECT: usize = 46;
|
||||
pub const SYS_FSTAT: usize = 47;
|
||||
#[allow(dead_code)]
|
||||
pub const SYS_GETCWD: usize = 48;
|
||||
#[allow(dead_code)]
|
||||
pub const SYS_GETPPID: usize = 49;
|
||||
#[allow(dead_code)]
|
||||
pub const SYS_GETPGID: usize = 50;
|
||||
|
||||
pub const SYS_FCNTL: usize = 51;
|
||||
@ -407,7 +405,7 @@ impl Syscall {
|
||||
///
|
||||
/// 这个函数内,需要根据系统调用号,调用对应的系统调用处理函数。
|
||||
/// 并且,对于用户态传入的指针参数,需要在本函数内进行越界检查,防止访问到内核空间。
|
||||
pub fn handle(syscall_num: usize, args: &[usize], from_user: bool) -> usize {
|
||||
pub fn handle(syscall_num: usize, args: &[usize], frame: &mut TrapFrame) -> usize {
|
||||
let r = match syscall_num {
|
||||
SYS_PUT_STRING => {
|
||||
Self::put_string(args[0] as *const u8, args[1] as u32, args[2] as u32)
|
||||
@ -437,7 +435,7 @@ impl Syscall {
|
||||
let len = args[2];
|
||||
let virt_addr: VirtAddr = VirtAddr::new(buf_vaddr);
|
||||
// 判断缓冲区是否来自用户态,进行权限校验
|
||||
let res = if from_user && verify_area(virt_addr, len as usize).is_err() {
|
||||
let res = if frame.from_user() && verify_area(virt_addr, len as usize).is_err() {
|
||||
// 来自用户态,而buffer在内核态,这样的操作不被允许
|
||||
Err(SystemError::EPERM)
|
||||
} else {
|
||||
@ -456,7 +454,7 @@ impl Syscall {
|
||||
let len = args[2];
|
||||
let virt_addr = VirtAddr::new(buf_vaddr);
|
||||
// 判断缓冲区是否来自用户态,进行权限校验
|
||||
let res = if from_user && verify_area(virt_addr, len as usize).is_err() {
|
||||
let res = if frame.from_user() && verify_area(virt_addr, len as usize).is_err() {
|
||||
// 来自用户态,而buffer在内核态,这样的操作不被允许
|
||||
Err(SystemError::EPERM)
|
||||
} else {
|
||||
@ -496,6 +494,9 @@ impl Syscall {
|
||||
res
|
||||
}
|
||||
|
||||
SYS_FORK => Self::fork(frame),
|
||||
SYS_VFORK => Self::vfork(frame),
|
||||
|
||||
SYS_BRK => {
|
||||
let new_brk = VirtAddr::new(args[0]);
|
||||
Self::brk(new_brk).map(|vaddr| vaddr.data())
|
||||
@ -503,7 +504,7 @@ impl Syscall {
|
||||
|
||||
SYS_SBRK => {
|
||||
let increment = args[0] as isize;
|
||||
Self::sbrk(increment).map(|vaddr| vaddr.data())
|
||||
Self::sbrk(increment).map(|vaddr: VirtAddr| vaddr.data())
|
||||
}
|
||||
|
||||
SYS_REBOOT => Self::reboot(),
|
||||
@ -518,7 +519,8 @@ impl Syscall {
|
||||
let virt_addr = VirtAddr::new(path_ptr as usize);
|
||||
// 权限校验
|
||||
if path_ptr.is_null()
|
||||
|| (from_user && verify_area(virt_addr, PAGE_2M_SIZE as usize).is_err())
|
||||
|| (frame.from_user()
|
||||
&& verify_area(virt_addr, PAGE_2M_SIZE as usize).is_err())
|
||||
{
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
@ -526,7 +528,7 @@ impl Syscall {
|
||||
let dest_path: &str = dest_path.to_str().map_err(|_| SystemError::EINVAL)?;
|
||||
if dest_path.len() == 0 {
|
||||
return Err(SystemError::EINVAL);
|
||||
} else if dest_path.len() > PAGE_4K_SIZE as usize {
|
||||
} else if dest_path.len() > MAX_PATHLEN as usize {
|
||||
return Err(SystemError::ENAMETOOLONG);
|
||||
}
|
||||
|
||||
@ -547,7 +549,7 @@ impl Syscall {
|
||||
let len = args[2];
|
||||
let virt_addr: VirtAddr = VirtAddr::new(buf_vaddr);
|
||||
// 判断缓冲区是否来自用户态,进行权限校验
|
||||
let res = if from_user && verify_area(virt_addr, len as usize).is_err() {
|
||||
let res = if frame.from_user() && verify_area(virt_addr, len as usize).is_err() {
|
||||
// 来自用户态,而buffer在内核态,这样的操作不被允许
|
||||
Err(SystemError::EPERM)
|
||||
} else if buf_vaddr == 0 {
|
||||
@ -570,37 +572,30 @@ impl Syscall {
|
||||
let virt_argv_ptr = VirtAddr::new(argv_ptr);
|
||||
let virt_env_ptr = VirtAddr::new(env_ptr);
|
||||
// 权限校验
|
||||
if from_user
|
||||
&& (verify_area(virt_path_ptr, PAGE_4K_SIZE as usize).is_err()
|
||||
if frame.from_user()
|
||||
&& (verify_area(virt_path_ptr, MAX_PATHLEN as usize).is_err()
|
||||
|| verify_area(virt_argv_ptr, PAGE_4K_SIZE as usize).is_err())
|
||||
|| verify_area(virt_env_ptr, PAGE_4K_SIZE as usize).is_err()
|
||||
{
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
Self::execve(
|
||||
path_ptr as *const c_void,
|
||||
argv_ptr as *const *const c_void,
|
||||
env_ptr as *const *const c_void,
|
||||
path_ptr as *const u8,
|
||||
argv_ptr as *const *const u8,
|
||||
env_ptr as *const *const u8,
|
||||
frame,
|
||||
)
|
||||
.map(|_| 0)
|
||||
}
|
||||
}
|
||||
SYS_WAIT4 => {
|
||||
let pid = args[0] as pid_t;
|
||||
let wstatus = args[1] as *mut c_int;
|
||||
let pid = args[0] as i64;
|
||||
let wstatus = args[1] as *mut i32;
|
||||
let options = args[2] as c_int;
|
||||
let rusage = args[3] as *mut c_void;
|
||||
let virt_wstatus = VirtAddr::new(wstatus as usize);
|
||||
let virt_rusage = VirtAddr::new(rusage as usize);
|
||||
// 权限校验
|
||||
// todo: 引入rusage之后,更正以下权限校验代码中,rusage的大小
|
||||
if from_user
|
||||
&& (verify_area(virt_wstatus, core::mem::size_of::<c_int>() as usize).is_err()
|
||||
|| verify_area(virt_rusage, PAGE_4K_SIZE as usize).is_err())
|
||||
{
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
Self::wait4(pid, wstatus, options, rusage)
|
||||
}
|
||||
Self::wait4(pid, wstatus, options, rusage)
|
||||
}
|
||||
|
||||
SYS_EXIT => {
|
||||
@ -613,7 +608,8 @@ impl Syscall {
|
||||
let virt_path_ptr = VirtAddr::new(path_ptr as usize);
|
||||
let security_check = || {
|
||||
if path_ptr.is_null()
|
||||
|| (from_user && verify_area(virt_path_ptr, PAGE_2M_SIZE as usize).is_err())
|
||||
|| (frame.from_user()
|
||||
&& verify_area(virt_path_ptr, PAGE_2M_SIZE as usize).is_err())
|
||||
{
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
@ -639,7 +635,7 @@ impl Syscall {
|
||||
let rem = args[1] as *mut TimeSpec;
|
||||
let virt_req = VirtAddr::new(req as usize);
|
||||
let virt_rem = VirtAddr::new(rem as usize);
|
||||
if from_user
|
||||
if frame.from_user()
|
||||
&& (verify_area(virt_req, core::mem::size_of::<TimeSpec>() as usize).is_err()
|
||||
|| verify_area(virt_rem, core::mem::size_of::<TimeSpec>() as usize)
|
||||
.is_err())
|
||||
@ -667,7 +663,7 @@ impl Syscall {
|
||||
let pathname = args[1] as *const c_char;
|
||||
let flags = args[2] as u32;
|
||||
let virt_pathname = VirtAddr::new(pathname as usize);
|
||||
if from_user && verify_area(virt_pathname, PAGE_4K_SIZE as usize).is_err() {
|
||||
if frame.from_user() && verify_area(virt_pathname, PAGE_4K_SIZE as usize).is_err() {
|
||||
Err(SystemError::EFAULT)
|
||||
} else if pathname.is_null() {
|
||||
Err(SystemError::EFAULT)
|
||||
@ -691,7 +687,7 @@ impl Syscall {
|
||||
}
|
||||
}
|
||||
SYS_KILL => {
|
||||
let pid = args[0] as pid_t;
|
||||
let pid = Pid::new(args[0]);
|
||||
let sig = args[1] as c_int;
|
||||
|
||||
Self::kill(pid, sig)
|
||||
@ -701,7 +697,7 @@ impl Syscall {
|
||||
let sig = args[0] as c_int;
|
||||
let act = args[1];
|
||||
let old_act = args[2];
|
||||
Self::sigaction(sig, act, old_act, from_user)
|
||||
Self::sigaction(sig, act, old_act, frame.from_user())
|
||||
}
|
||||
|
||||
SYS_RT_SIGRETURN => {
|
||||
@ -710,9 +706,9 @@ impl Syscall {
|
||||
todo!()
|
||||
}
|
||||
|
||||
SYS_GETPID => Self::getpid(),
|
||||
SYS_GETPID => Self::getpid().map(|pid| pid.into()),
|
||||
|
||||
SYS_SCHED => Self::sched(from_user),
|
||||
SYS_SCHED => Self::sched(frame.from_user()),
|
||||
SYS_DUP => {
|
||||
let oldfd: i32 = args[0] as c_int;
|
||||
Self::dup(oldfd)
|
||||
@ -919,6 +915,25 @@ impl Syscall {
|
||||
}
|
||||
}
|
||||
|
||||
SYS_GETCWD => {
|
||||
let buf = args[0] as *mut u8;
|
||||
let size = args[1] as usize;
|
||||
let security_check = || {
|
||||
verify_area(VirtAddr::new(buf as usize), size)?;
|
||||
return Ok(());
|
||||
};
|
||||
let r = security_check();
|
||||
if r.is_err() {
|
||||
Err(r.unwrap_err())
|
||||
} else {
|
||||
let buf = unsafe { core::slice::from_raw_parts_mut(buf, size) };
|
||||
Self::getcwd(buf).map(|ptr| ptr.data())
|
||||
}
|
||||
}
|
||||
|
||||
SYS_GETPGID => Self::getpgid(Pid::new(args[0])).map(|pid| pid.into()),
|
||||
|
||||
SYS_GETPPID => Self::getppid().map(|pid| pid.into()),
|
||||
SYS_FSTAT => {
|
||||
let fd = args[0] as i32;
|
||||
let kstat = args[1] as *mut PosixKstat;
|
||||
|
@ -1,9 +1,7 @@
|
||||
#include "syscall.h"
|
||||
#include <common/errno.h>
|
||||
#include <common/fcntl.h>
|
||||
#include <common/kthread.h>
|
||||
#include <common/string.h>
|
||||
#include <driver/disk/ahci/ahci.h>
|
||||
#include <exception/gate.h>
|
||||
#include <exception/irq.h>
|
||||
#include <filesystem/vfs/VFS.h>
|
||||
@ -13,13 +11,6 @@
|
||||
// 导出系统调用入口函数,定义在entry.S中
|
||||
extern void syscall_int(void);
|
||||
|
||||
/**
|
||||
* @brief 重新定义为:把系统调用函数加入系统调用表
|
||||
* @param syscall_num 系统调用号
|
||||
* @param symbol 系统调用处理函数
|
||||
*/
|
||||
#define SYSCALL_COMMON(syscall_num, symbol) [syscall_num] = symbol,
|
||||
|
||||
/**
|
||||
* @brief 通过中断进入系统调用
|
||||
*
|
||||
@ -73,45 +64,4 @@ ul do_put_string(char *s, uint32_t front_color, uint32_t background_color)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 等待进程退出
|
||||
*
|
||||
* @param pid 目标进程id
|
||||
* @param status 返回的状态信息
|
||||
* @param options 等待选项
|
||||
* @param rusage
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t c_sys_wait4(pid_t pid, int *status, int options, void *rusage)
|
||||
{
|
||||
|
||||
struct process_control_block *proc = NULL;
|
||||
struct process_control_block *child_proc = NULL;
|
||||
|
||||
// 查找pid为指定值的进程
|
||||
// ps: 这里判断子进程的方法没有按照posix 2008来写。
|
||||
// todo: 根据进程树判断是否为当前进程的子进程
|
||||
// todo: 当进程管理模块拥有pcblist_lock之后,调用之前,应当对其加锁
|
||||
child_proc = process_find_pcb_by_pid(pid);
|
||||
|
||||
if (child_proc == NULL)
|
||||
return -ECHILD;
|
||||
|
||||
// 暂时不支持options选项,该值目前必须为0
|
||||
if (options != 0)
|
||||
return -EINVAL;
|
||||
|
||||
// 如果子进程没有退出,则等待其退出
|
||||
// BUG: 这里存在问题,由于未对进程管理模块加锁,因此可能会出现子进程退出后,父进程还在等待的情况
|
||||
// (子进程退出后,process_exit_notify消息丢失)
|
||||
while (child_proc->state != PROC_ZOMBIE)
|
||||
wait_queue_sleep_on_interriptible(¤t_pcb->wait_child_proc_exit);
|
||||
|
||||
// 拷贝子进程的返回码
|
||||
if (likely(status != NULL))
|
||||
*status = child_proc->exit_code;
|
||||
// copy_to_user(status, (void*)child_proc->exit_code, sizeof(int));
|
||||
|
||||
process_release_pcb(child_proc);
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user