diff --git a/kernel/src/arch/x86_64/syscall.rs b/kernel/src/arch/x86_64/syscall.rs index 966e5873b..9f60733b1 100644 --- a/kernel/src/arch/x86_64/syscall.rs +++ b/kernel/src/arch/x86_64/syscall.rs @@ -13,6 +13,8 @@ use alloc::string::String; use super::{interrupt::TrapFrame, mm::barrier::mfence}; +pub const SYS_PRLIMIT64: usize = 302; + /// ### 存储PCB系统调用栈以及在syscall过程中暂存用户态rsp的结构体 /// /// 在syscall指令中将会从该结构体中读取系统调用栈和暂存rsp, @@ -65,7 +67,7 @@ pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) -> () { ]; mfence(); - // 由于进程管理未完成重构,有些系统调用需要在这里临时处理,以后这里的特殊处理要删掉。 + // Arch specific syscall match syscall_num { SYS_RT_SIGRETURN => { syscall_return!(X86_64SignalArch::sys_rt_sigreturn(frame) as usize, frame); diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index 78d9c822c..e21aabc48 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -417,7 +417,7 @@ pub struct FileDescriptorVec { } impl FileDescriptorVec { - pub const PROCESS_MAX_FD: usize = 32; + pub const PROCESS_MAX_FD: usize = 1024; pub fn new() -> FileDescriptorVec { // 先声明一个未初始化的数组 diff --git a/kernel/src/process/resource.rs b/kernel/src/process/resource.rs index 7f187fff3..7ce3dfe4d 100644 --- a/kernel/src/process/resource.rs +++ b/kernel/src/process/resource.rs @@ -1,3 +1,5 @@ +use num_traits::FromPrimitive; + use crate::{syscall::SystemError, time::TimeSpec}; use super::ProcessControlBlock; @@ -71,6 +73,69 @@ impl TryFrom for RUsageWho { } } +/// Resource limit +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(C)] +pub struct RLimit64 { + /// The current (soft) limit + pub rlim_cur: u64, + /// The hard limit + pub rlim_max: u64, +} + +/// Resource limit IDs +/// +/// ## Note +/// +/// 有些架构中,这里[5,9]的值是不同的,我们将来需要在这里增加条件编译 +#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive)] +pub enum RLimitID { + /// CPU time in sec + Cpu = 0, + /// Maximum file size + Fsize = 1, + /// Max data size + Data = 2, + /// Max stack size + Stack = 3, + /// Max core file size + Core = 4, + /// Max resident set size + Rss = 5, + + /// Max number of processes + Nproc = 6, + /// Max number of open files + Nofile = 7, + /// Max locked-in-memory address space + Memlock = 8, + /// Address space limit + As = 9, + /// Max number of file locks held + Locks = 10, + + /// Max number of pending signals + Sigpending = 11, + /// Max bytes in POSIX mqueues + Msgqueue = 12, + /// Max nice prio allowed to raise to + /// 0-39 for nice level 19 .. -20 + Nice = 13, + /// Max realtime priority + Rtprio = 14, + /// Timeout for RT tasks in us + Rttime = 15, + Nlimits = 16, +} + +impl TryFrom for RLimitID { + type Error = SystemError; + + fn try_from(value: usize) -> Result { + ::from_usize(value).ok_or(SystemError::EINVAL) + } +} + impl ProcessControlBlock { /// 获取进程资源使用情况 /// diff --git a/kernel/src/process/syscall.rs b/kernel/src/process/syscall.rs index 14a629ce7..aeee06077 100644 --- a/kernel/src/process/syscall.rs +++ b/kernel/src/process/syscall.rs @@ -9,15 +9,18 @@ use alloc::{ use super::{ abi::WaitOption, fork::{CloneFlags, KernelCloneArgs}, - resource::{RUsage, RUsageWho}, + resource::{RLimit64, RLimitID, RUsage, RUsageWho}, KernelStack, Pid, ProcessManager, ProcessState, }; use crate::{ - arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch}, + arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch, MMArch}, exception::InterruptArch, - filesystem::{procfs::procfs_register_pid, vfs::MAX_PATHLEN}, + filesystem::{ + procfs::procfs_register_pid, + vfs::{file::FileDescriptorVec, MAX_PATHLEN}, + }, include::bindings::bindings::verify_area, - mm::VirtAddr, + mm::{ucontext::UserStack, MemoryManagementArch, VirtAddr}, process::ProcessControlBlock, sched::completion::Completion, syscall::{ @@ -333,4 +336,77 @@ impl Syscall { return Ok(0); } + + /// # 设置资源限制 + /// + /// TODO: 目前暂时不支持设置资源限制,只提供读取默认值的功能 + /// + /// ## 参数 + /// + /// - pid: 进程号 + /// - resource: 资源类型 + /// - new_limit: 新的资源限制 + /// - old_limit: 旧的资源限制 + /// + /// ## 返回值 + /// + /// - 成功,0 + /// - 如果old_limit不为NULL,则返回旧的资源限制到old_limit + /// + pub fn prlimit64( + _pid: Pid, + resource: usize, + new_limit: *const RLimit64, + old_limit: *mut RLimit64, + ) -> Result { + let resource = RLimitID::try_from(resource)?; + let mut writer = None; + + if new_limit.is_null() { + return Err(SystemError::EINVAL); + } + + if !old_limit.is_null() { + writer = Some(UserBufferWriter::new( + old_limit, + core::mem::size_of::(), + true, + )?); + } + + let _reader = UserBufferReader::new(new_limit, core::mem::size_of::(), true)?; + + match resource { + RLimitID::Stack => { + if let Some(mut writer) = writer { + let mut rlimit = writer.buffer::(0).unwrap()[0]; + rlimit.rlim_cur = UserStack::DEFAULT_USER_STACK_SIZE as u64; + rlimit.rlim_max = UserStack::DEFAULT_USER_STACK_SIZE as u64; + } + return Ok(0); + } + + RLimitID::Nofile => { + if let Some(mut writer) = writer { + let mut rlimit = writer.buffer::(0).unwrap()[0]; + rlimit.rlim_cur = FileDescriptorVec::PROCESS_MAX_FD as u64; + rlimit.rlim_max = FileDescriptorVec::PROCESS_MAX_FD as u64; + } + return Ok(0); + } + + RLimitID::As | RLimitID::Rss => { + if let Some(mut writer) = writer { + let mut rlimit = writer.buffer::(0).unwrap()[0]; + rlimit.rlim_cur = MMArch::USER_END_VADDR.data() as u64; + rlimit.rlim_max = MMArch::USER_END_VADDR.data() as u64; + } + return Ok(0); + } + + _ => { + return Err(SystemError::ENOSYS); + } + } + } } diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index f92f0762e..6b9c5851e 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -4,8 +4,12 @@ use core::{ }; use crate::{ + arch::syscall::SYS_PRLIMIT64, libs::{futex::constant::FutexFlag, rand::GRandFlags}, - process::{fork::KernelCloneArgs, resource::RUsage}, + process::{ + fork::KernelCloneArgs, + resource::{RLimit64, RUsage}, + }, }; use num_traits::{FromPrimitive, ToPrimitive}; @@ -1190,6 +1194,16 @@ impl Syscall { Self::readlink_at(dirfd, pathname, buf, bufsiz) } + SYS_PRLIMIT64 => { + let pid = args[0]; + let pid = Pid::new(pid); + let resource = args[1]; + let new_limit = args[2] as *const RLimit64; + let old_limit = args[3] as *mut RLimit64; + + Self::prlimit64(pid, resource, new_limit, old_limit) + } + _ => panic!("Unsupported syscall ID: {}", syscall_num), }; return r; diff --git a/user/apps/shell/cmd.c b/user/apps/shell/cmd.c index d506ce071..f412d14e0 100644 --- a/user/apps/shell/cmd.c +++ b/user/apps/shell/cmd.c @@ -521,7 +521,7 @@ int shell_cmd_exec(int argc, char **argv) char *file_path = get_target_filepath(argv[1], &path_len); // printf("before execv, path=%s, argc=%d\n", file_path, argc); - char **real_argv; + char **real_argv = NULL; if (argc > 1) { real_argv = &argv[1];