Skip to content

Commit

Permalink
添加prlimit64系统调用 (#438)
Browse files Browse the repository at this point in the history
注意: 目前仅支持读取默认的rlimit值,尚不支持设置rlimit值.
  • Loading branch information
fslongjin authored Nov 12, 2023
1 parent 4a2d719 commit 0d9b7d9
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 8 deletions.
4 changes: 3 additions & 1 deletion kernel/src/arch/x86_64/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/filesystem/vfs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
// 先声明一个未初始化的数组
Expand Down
65 changes: 65 additions & 0 deletions kernel/src/process/resource.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use num_traits::FromPrimitive;

use crate::{syscall::SystemError, time::TimeSpec};

use super::ProcessControlBlock;
Expand Down Expand Up @@ -71,6 +73,69 @@ impl TryFrom<i32> 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<usize> for RLimitID {
type Error = SystemError;

fn try_from(value: usize) -> Result<Self, Self::Error> {
<Self as FromPrimitive>::from_usize(value).ok_or(SystemError::EINVAL)
}
}

impl ProcessControlBlock {
/// 获取进程资源使用情况
///
Expand Down
84 changes: 80 additions & 4 deletions kernel/src/process/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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<usize, SystemError> {
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::<RLimit64>(),
true,
)?);
}

let _reader = UserBufferReader::new(new_limit, core::mem::size_of::<RLimit64>(), true)?;

match resource {
RLimitID::Stack => {
if let Some(mut writer) = writer {
let mut rlimit = writer.buffer::<RLimit64>(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::<RLimit64>(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::<RLimit64>(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);
}
}
}
}
16 changes: 15 additions & 1 deletion kernel/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion user/apps/shell/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down

0 comments on commit 0d9b7d9

Please sign in to comment.