进程管理模块重构完成 (#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:
LoGin
2023-09-15 14:58:19 +08:00
committed by GitHub
parent b087521e07
commit 1496ba7b24
153 changed files with 4895 additions and 8190 deletions

View File

@ -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;

View File

@ -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(&current_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;
}