feat(process): 新增进程资源限制(rlimit)管理功能及相关系统调用 (#1300)

-
为ProcessControlBlock添加rlimits字段,存储进程资源限制,默认初始化典型值(如nofi
le软限制1024、硬限制65536)
- 实现进程rlimit的获取、设置及继承机制(inherit_rlimits_from)
- 在dup2、fcntl等函数中添加RLIMIT_NOFILE检查,确保文件描述符不超过软限制
- 实现sys_prlimit64和sys_setrlimit系统调用,支持查询和设置进程资源限制
- 调整测试用例,添加dup_test到gvisor白名单,忽略未支持的测试

Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
LoGin 2025-09-27 22:01:34 +08:00 committed by GitHub
parent 1e90730d34
commit afc09a460b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 346 additions and 72 deletions

View File

@ -1,4 +1,4 @@
use core::sync::atomic::{AtomicUsize, Ordering};
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use alloc::{string::String, sync::Arc, vec::Vec};
use log::error;
@ -129,6 +129,8 @@ pub struct File {
pub private_data: SpinLock<FilePrivateData>,
/// 文件的凭证
cred: Arc<Cred>,
/// 文件描述符标志是否在execve时关闭
close_on_exec: AtomicBool,
}
impl File {
@ -136,7 +138,7 @@ impl File {
///
/// @param inode 文件对象对应的inode
/// @param mode 文件的打开模式
pub fn new(inode: Arc<dyn IndexNode>, mode: FileMode) -> Result<Self, SystemError> {
pub fn new(inode: Arc<dyn IndexNode>, mut mode: FileMode) -> Result<Self, SystemError> {
let mut inode = inode;
let file_type = inode.metadata()?.file_type;
if file_type == FileType::Pipe {
@ -144,6 +146,8 @@ impl File {
inode = pipe_inode;
}
}
let close_on_exec = mode.contains(FileMode::O_CLOEXEC);
mode.remove(FileMode::O_CLOEXEC);
let private_data = SpinLock::new(FilePrivateData::default());
inode.open(private_data.lock(), &mode)?;
@ -156,6 +160,7 @@ impl File {
readdir_subdirs_name: SpinLock::new(Vec::default()),
private_data,
cred: ProcessManager::current_pcb().cred(),
close_on_exec: AtomicBool::new(close_on_exec),
};
return Ok(f);
@ -409,6 +414,7 @@ impl File {
readdir_subdirs_name: SpinLock::new(self.readdir_subdirs_name.lock().clone()),
private_data: SpinLock::new(self.private_data.lock().clone()),
cred: self.cred.clone(),
close_on_exec: AtomicBool::new(self.close_on_exec.load(Ordering::SeqCst)),
};
// 调用inode的open方法让inode知道有新的文件打开了这个inode
// TODO: reopen is not a good idea for some inodes, need a better design
@ -438,25 +444,27 @@ impl File {
/// 获取文件是否在execve时关闭
#[inline]
pub fn close_on_exec(&self) -> bool {
return self.mode().contains(FileMode::O_CLOEXEC);
return self.close_on_exec.load(Ordering::SeqCst);
}
/// 设置文件是否在execve时关闭
#[inline]
pub fn set_close_on_exec(&self, close_on_exec: bool) {
let mut mode_guard = self.mode.write();
if close_on_exec {
mode_guard.insert(FileMode::O_CLOEXEC);
} else {
mode_guard.remove(FileMode::O_CLOEXEC);
}
self.close_on_exec.store(close_on_exec, Ordering::SeqCst);
}
pub fn set_mode(&self, mode: FileMode) -> Result<(), SystemError> {
pub fn set_mode(&self, mut mode: FileMode) -> Result<(), SystemError> {
// todo: 是否需要调用inode的open方法以更新private data假如它与mode有关的话?
// 也许需要加个更好的设计让inode知晓文件的打开模式发生了变化让它自己决定是否需要更新private data
// 直接修改文件的打开模式
// 提取 O_CLOEXEC 状态并更新 close_on_exec 字段
let close_on_exec = mode.contains(FileMode::O_CLOEXEC);
self.close_on_exec.store(close_on_exec, Ordering::SeqCst);
// 从 mode 中移除 O_CLOEXEC 标志,保持与构造函数一致的行为
mode.remove(FileMode::O_CLOEXEC);
// 更新文件的打开模式
*self.mode.write() = mode;
self.private_data.lock().update_mode(mode);
return Ok(());
@ -528,12 +536,15 @@ impl Default for FileDescriptorVec {
}
}
impl FileDescriptorVec {
pub const PROCESS_MAX_FD: usize = 1024;
/// 文件描述符表的初始容量
pub const INITIAL_CAPACITY: usize = 1024;
/// 文件描述符表的最大容量限制(防止无限扩容)
pub const MAX_CAPACITY: usize = 65536;
#[inline(never)]
pub fn new() -> FileDescriptorVec {
let mut data = Vec::with_capacity(FileDescriptorVec::PROCESS_MAX_FD);
data.resize(FileDescriptorVec::PROCESS_MAX_FD, None);
let mut data = Vec::with_capacity(FileDescriptorVec::INITIAL_CAPACITY);
data.resize(FileDescriptorVec::INITIAL_CAPACITY, None);
// 初始化文件描述符数组结构体
return FileDescriptorVec { fds: data };
@ -544,7 +555,10 @@ impl FileDescriptorVec {
/// @return FileDescriptorVec 克隆后的文件描述符数组
pub fn clone(&self) -> FileDescriptorVec {
let mut res = FileDescriptorVec::new();
for i in 0..FileDescriptorVec::PROCESS_MAX_FD {
// 调整容量以匹配源文件描述符表
let _ = res.resize_to_capacity(self.fds.len());
for i in 0..self.fds.len() {
if let Some(file) = &self.fds[i] {
if let Some(file) = file.try_clone() {
res.fds[i] = Some(Arc::new(file));
@ -554,6 +568,46 @@ impl FileDescriptorVec {
return res;
}
/// 返回当前已占用的最高文件描述符索引若无则为None
#[inline]
fn highest_open_index(&self) -> Option<usize> {
// 从高到低查找第一个占用的槽位
(0..self.fds.len()).rev().find(|&i| self.fds[i].is_some())
}
/// 扩容文件描述符表到指定容量
///
/// ## 参数
/// - `new_capacity`: 新的容量大小
///
/// ## 返回值
/// - `Ok(())`: 扩容成功
/// - `Err(SystemError)`: 扩容失败
fn resize_to_capacity(&mut self, new_capacity: usize) -> Result<(), SystemError> {
if new_capacity > FileDescriptorVec::MAX_CAPACITY {
return Err(SystemError::EMFILE);
}
let current_len = self.fds.len();
if new_capacity > current_len {
// 扩容扩展向量并填充None
// 使用 try_reserve 先检查内存分配是否可能成功
if self.fds.try_reserve(new_capacity - current_len).is_err() {
return Err(SystemError::ENOMEM);
}
self.fds.resize(new_capacity, None);
} else if new_capacity < current_len {
// 缩容允许但不能丢弃仍在使用的高位fd。
// 若高位fd仍在使用将缩容目标提升到 (最高已用fd + 1)。
let floor = self.highest_open_index().map(|idx| idx + 1).unwrap_or(0);
let target = core::cmp::max(new_capacity, floor);
if target < current_len {
self.fds.truncate(target);
}
}
Ok(())
}
/// 返回 `已经打开的` 文件描述符的数量
pub fn fd_open_count(&self) -> usize {
let mut size = 0;
@ -571,8 +625,8 @@ impl FileDescriptorVec {
///
/// @return false 不合法
#[inline]
pub fn validate_fd(fd: i32) -> bool {
return !(fd < 0 || fd as usize > FileDescriptorVec::PROCESS_MAX_FD);
pub fn validate_fd(&self, fd: i32) -> bool {
return !(fd < 0 || fd as usize >= self.fds.len());
}
/// 申请文件描述符,并把文件对象存入其中。
@ -587,7 +641,22 @@ impl FileDescriptorVec {
/// - `Ok(i32)` 申请成功,返回申请到的文件描述符
/// - `Err(SystemError)` 申请失败返回错误码并且file对象将被drop掉
pub fn alloc_fd(&mut self, file: File, fd: Option<i32>) -> Result<i32, SystemError> {
// 获取RLIMIT_NOFILE限制
let nofile_limit = crate::process::ProcessManager::current_pcb()
.get_rlimit(crate::process::resource::RLimitID::Nofile)
.rlim_cur as usize;
if let Some(new_fd) = fd {
// 检查指定的文件描述符是否在有效范围内
if new_fd < 0 || new_fd as usize >= nofile_limit {
return Err(SystemError::EMFILE);
}
// 如果指定的fd超出当前容量需要扩容
if new_fd as usize >= self.fds.len() {
self.resize_to_capacity(new_fd as usize + 1)?;
}
let x = &mut self.fds[new_fd as usize];
if x.is_none() {
*x = Some(Arc::new(file));
@ -596,8 +665,9 @@ impl FileDescriptorVec {
return Err(SystemError::EBADF);
}
} else {
// 没有指定要申请的文件描述符编号
for i in 0..FileDescriptorVec::PROCESS_MAX_FD {
// 没有指定要申请的文件描述符编号,在有效范围内查找空位
let max_search = core::cmp::min(self.fds.len(), nofile_limit);
for i in 0..max_search {
if self.fds[i].is_none() {
self.fds[i] = Some(Arc::new(file));
return Ok(i as i32);
@ -613,12 +683,37 @@ impl FileDescriptorVec {
///
/// - `fd` 文件描述符序号
pub fn get_file_by_fd(&self, fd: i32) -> Option<Arc<File>> {
if !FileDescriptorVec::validate_fd(fd) {
if !self.validate_fd(fd) {
return None;
}
self.fds[fd as usize].clone()
}
/// 当RLIMIT_NOFILE变化时调整文件描述符表容量
///
/// ## 参数
/// - `new_rlimit_nofile`: 新的RLIMIT_NOFILE值
///
/// ## 返回值
/// - `Ok(())`: 调整成功
/// - `Err(SystemError)`: 调整失败
pub fn adjust_for_rlimit_change(
&mut self,
new_rlimit_nofile: usize,
) -> Result<(), SystemError> {
// 目标容量不超过实现上限
let desired = core::cmp::min(new_rlimit_nofile, FileDescriptorVec::MAX_CAPACITY);
if desired >= self.fds.len() {
// rlimit 变大:扩容到 desired
self.resize_to_capacity(desired)
} else {
// rlimit 变小:按用户建议,缩容到 max(desired, 最高已用fd+1)
let floor = self.highest_open_index().map(|idx| idx + 1).unwrap_or(0);
let target = core::cmp::max(desired, floor);
self.resize_to_capacity(target)
}
}
/// 释放文件描述符,同时关闭文件。
///
/// ## 参数
@ -638,7 +733,7 @@ impl FileDescriptorVec {
}
pub fn close_on_exec(&mut self) {
for i in 0..FileDescriptorVec::PROCESS_MAX_FD {
for i in 0..self.fds.len() {
if let Some(file) = &self.fds[i] {
let to_drop = file.close_on_exec();
if to_drop {
@ -672,7 +767,7 @@ impl Iterator for FileDescriptorIterator<'_> {
type Item = (i32, Arc<File>);
fn next(&mut self) -> Option<Self::Item> {
while self.index < FileDescriptorVec::PROCESS_MAX_FD {
while self.index < self.fds.fds.len() {
let fd = self.index as i32;
self.index += 1;
if let Some(file) = self.fds.get_file_by_fd(fd) {

View File

@ -19,8 +19,16 @@ pub fn do_dup3(
flags: FileMode,
fd_table_guard: &mut RwLockWriteGuard<'_, FileDescriptorVec>,
) -> Result<usize, SystemError> {
// 检查 RLIMIT_NOFILEnewfd 必须小于软限制
let nofile = crate::process::ProcessManager::current_pcb()
.get_rlimit(crate::process::resource::RLimitID::Nofile)
.rlim_cur;
if newfd as u64 >= nofile {
return Err(SystemError::EMFILE);
}
// 确认oldfd, newid是否有效
if !(FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd)) {
if !(fd_table_guard.validate_fd(oldfd) && fd_table_guard.validate_fd(newfd)) {
return Err(SystemError::EBADF);
}

View File

@ -3,7 +3,7 @@ use crate::{
arch::interrupt::TrapFrame,
filesystem::vfs::{
fcntl::{FcntlCommand, FD_CLOEXEC},
file::{FileDescriptorVec, FileMode},
file::FileMode,
syscall::dup2::{do_dup2, do_dup3},
},
process::ProcessManager,
@ -70,13 +70,19 @@ impl SysFcntlHandle {
// debug!("fcntl ({cmd:?}) fd: {fd}, arg={arg}");
match cmd {
FcntlCommand::DupFd | FcntlCommand::DupFdCloexec => {
if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD {
// RLIMIT_NOFILE 检查
let nofile = ProcessManager::current_pcb()
.get_rlimit(crate::process::resource::RLimitID::Nofile)
.rlim_cur as usize;
if arg < 0 || arg as usize >= nofile {
return Err(SystemError::EBADF);
}
let arg = arg as usize;
for i in arg..FileDescriptorVec::PROCESS_MAX_FD {
let binding = ProcessManager::current_pcb().fd_table();
let mut fd_table_guard = binding.write();
let binding = ProcessManager::current_pcb().fd_table();
let mut fd_table_guard = binding.write();
// 在RLIMIT_NOFILE范围内查找可用的文件描述符
for i in arg..nofile {
if fd_table_guard.get_file_by_fd(i as i32).is_none() {
if cmd == FcntlCommand::DupFd {
return do_dup2(fd, i as i32, &mut fd_table_guard);

View File

@ -4,7 +4,6 @@ use system_error::SystemError;
use crate::arch::interrupt::TrapFrame;
use crate::arch::syscall::nr::{SYS_GETDENTS, SYS_GETDENTS64};
use crate::filesystem::vfs::file::FileDescriptorVec;
use crate::filesystem::vfs::FilldirContext;
use crate::mm::{verify_area, VirtAddr};
use crate::process::ProcessManager;
@ -48,7 +47,7 @@ impl Syscall for SysGetdentsHandle {
let buf: &mut [u8] = unsafe {
core::slice::from_raw_parts_mut::<'static, u8>(buf_vaddr as *mut u8, len)
};
if fd < 0 || fd as usize > FileDescriptorVec::PROCESS_MAX_FD {
if fd < 0 {
return Err(SystemError::EBADF);
}

View File

@ -482,6 +482,9 @@ impl ProcessManager {
)
});
// 继承 rlimit
pcb.inherit_rlimits_from(current_pcb);
// log::debug!("fork: clone_flags: {:?}", clone_flags);
// 设置线程组id、组长
if clone_flags.contains(CloneFlags::CLONE_THREAD) {

View File

@ -57,6 +57,7 @@ use crate::{
PhysAddr, VirtAddr,
},
net::socket::Socket,
process::resource::{RLimit64, RLimitID},
sched::{
DequeueFlag, EnqueueFlag, OnRq, SchedMode, WakeupFlags, __schedule, completion::Completion,
cpu_rq, fair::FairSchedEntity, prio::MAX_PRIO,
@ -778,6 +779,8 @@ pub struct ProcessControlBlock {
/// 进程的可执行文件路径
executable_path: RwLock<String>,
/// 资源限制rlimit数组
rlimits: RwLock<[RLimit64; RLimitID::Nlimits as usize]>,
}
impl ProcessControlBlock {
@ -896,6 +899,7 @@ impl ProcessControlBlock {
self_ref: weak.clone(),
restart_block: SpinLock::new(None),
executable_path: RwLock::new(name),
rlimits: RwLock::new(Self::default_rlimits()),
};
pcb.sig_info.write().set_tty(tty);
@ -929,6 +933,123 @@ impl ProcessControlBlock {
return pcb;
}
fn default_rlimits() -> [crate::process::resource::RLimit64; RLimitID::Nlimits as usize] {
use crate::mm::ucontext::UserStack;
use crate::process::resource::{RLimit64, RLimitID};
let mut arr = [RLimit64 {
rlim_cur: 0,
rlim_max: 0,
}; RLimitID::Nlimits as usize];
// Linux 典型默认值软限制1024硬限制65536
// 文件描述符表会根据RLIMIT_NOFILE自动扩容
arr[RLimitID::Nofile as usize] = RLimit64 {
rlim_cur: 1024,
rlim_max: 65536,
};
arr[RLimitID::Stack as usize] = RLimit64 {
rlim_cur: UserStack::DEFAULT_USER_STACK_SIZE as u64,
rlim_max: UserStack::DEFAULT_USER_STACK_SIZE as u64,
};
arr[RLimitID::As as usize] = {
let end = <crate::arch::MMArch as crate::mm::MemoryManagementArch>::USER_END_VADDR;
RLimit64 {
rlim_cur: end.data() as u64,
rlim_max: end.data() as u64,
}
};
arr[RLimitID::Rss as usize] = arr[RLimitID::As as usize];
arr
}
#[inline(always)]
pub fn get_rlimit(&self, res: RLimitID) -> crate::process::resource::RLimit64 {
self.rlimits.read()[res as usize]
}
pub fn set_rlimit(
&self,
res: RLimitID,
newv: crate::process::resource::RLimit64,
) -> Result<(), system_error::SystemError> {
use system_error::SystemError;
if newv.rlim_cur > newv.rlim_max {
return Err(SystemError::EINVAL);
}
// 注意允许RLIMIT_NOFILE设置为0这是测试用例的预期行为
// 当rlim_cur为0时无法分配新的文件描述符但现有fd仍可使用
// 对于RLIMIT_NOFILE检查是否超过系统实现的最大容量限制
if res == RLimitID::Nofile {
if newv.rlim_cur > FileDescriptorVec::MAX_CAPACITY as u64 {
return Err(SystemError::EINVAL);
}
if newv.rlim_max > FileDescriptorVec::MAX_CAPACITY as u64 {
return Err(SystemError::EINVAL);
}
}
let cur = self.rlimits.read()[res as usize];
if newv.rlim_max > cur.rlim_max {
let cred = self.cred();
if !cred.has_capability(crate::process::cred::CAPFlags::CAP_SYS_RESOURCE) {
return Err(SystemError::EPERM);
}
}
// 更新rlimit
self.rlimits.write()[res as usize] = newv;
// 如果是RLIMIT_NOFILE变化调整文件描述符表
if res == RLimitID::Nofile {
if let Err(e) = self.adjust_fd_table_for_rlimit_change(newv.rlim_cur as usize) {
// 如果调整失败回滚rlimit设置
self.rlimits.write()[res as usize] = cur;
return Err(e);
}
}
Ok(())
}
/// 继承父进程的全部rlimit
pub fn inherit_rlimits_from(&self, parent: &Arc<ProcessControlBlock>) {
let src = *parent.rlimits.read();
*self.rlimits.write() = src;
// 继承后调整文件描述符表以匹配新的RLIMIT_NOFILE
let nofile_limit = src[RLimitID::Nofile as usize].rlim_cur as usize;
if let Err(e) = self.adjust_fd_table_for_rlimit_change(nofile_limit) {
// 如果调整失败,记录错误但不影响继承过程
error!(
"Failed to adjust fd table after inheriting rlimits: {:?}",
e
);
}
}
/// 当RLIMIT_NOFILE变化时调整文件描述符表
///
/// ## 参数
/// - `new_rlimit_nofile`: 新的RLIMIT_NOFILE值
///
/// ## 返回值
/// - `Ok(())`: 调整成功
/// - `Err(SystemError)`: 调整失败
fn adjust_fd_table_for_rlimit_change(
&self,
new_rlimit_nofile: usize,
) -> Result<(), system_error::SystemError> {
let fd_table = self.basic.read().try_fd_table().unwrap();
let mut fd_table_guard = fd_table.write();
fd_table_guard.adjust_for_rlimit_change(new_rlimit_nofile)
}
/// 返回当前进程的锁持有计数
#[inline(always)]
pub fn preempt_count(&self) -> usize {

View File

@ -15,7 +15,7 @@ mod sys_getsid;
mod sys_gettid;
mod sys_getuid;
mod sys_groups;
mod sys_prlimit64;
pub mod sys_prlimit64;
mod sys_set_tid_address;
mod sys_setdomainname;
mod sys_setfsgid;
@ -39,4 +39,6 @@ mod sys_getpgrp;
#[cfg(target_arch = "x86_64")]
mod sys_getrlimit;
#[cfg(target_arch = "x86_64")]
mod sys_setrlimit;
#[cfg(target_arch = "x86_64")]
mod sys_vfork;

View File

@ -2,14 +2,11 @@ use crate::arch::syscall::nr::SYS_PRLIMIT64;
use crate::syscall::table::FormattedSyscallParam;
use crate::syscall::table::Syscall;
use crate::{
arch::MMArch,
filesystem::vfs::file::FileDescriptorVec,
mm::{ucontext::UserStack, MemoryManagementArch},
process::{
resource::{RLimit64, RLimitID},
RawPid,
ProcessManager, RawPid,
},
syscall::user_access::UserBufferWriter,
syscall::user_access::{UserBufferReader, UserBufferWriter},
};
use alloc::vec::Vec;
use system_error::SystemError;
@ -83,15 +80,14 @@ syscall_table_macros::declare_syscall!(SYS_PRLIMIT64, SysPrlimit64);
/// - 成功0
/// - 如果old_limit不为NULL则返回旧的资源限制到old_limit
///
pub(super) fn do_prlimit64(
_pid: RawPid,
pub fn do_prlimit64(
pid: RawPid,
resource: usize,
_new_limit: *const RLimit64,
new_limit: *const RLimit64,
old_limit: *mut RLimit64,
) -> Result<usize, SystemError> {
let resource = RLimitID::try_from(resource)?;
let mut writer = None;
if !old_limit.is_null() {
writer = Some(UserBufferWriter::new(
old_limit,
@ -100,36 +96,29 @@ pub(super) fn do_prlimit64(
)?);
}
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);
}
// 找到目标进程(仅支持当前命名空间可见)
let target = if pid.data() == 0 {
ProcessManager::current_pcb()
} else {
ProcessManager::find_task_by_vpid(pid).ok_or(SystemError::ESRCH)?
};
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);
}
// 读取旧限制
if let Some(mut writer) = writer {
let cur = target.get_rlimit(resource);
let rlimit = writer.buffer::<RLimit64>(0)?;
rlimit[0].rlim_cur = cur.rlim_cur;
rlimit[0].rlim_max = cur.rlim_max;
}
// 设置新限制
if !new_limit.is_null() {
// 从用户拷贝新值
let reader = UserBufferReader::new(new_limit, core::mem::size_of::<RLimit64>(), true)?;
let newval = *reader.read_one_from_user::<RLimit64>(0)?;
// 应用到目标进程
target.set_rlimit(resource, newval)?;
}
Ok(0)
}

View File

@ -0,0 +1,50 @@
use system_error::SystemError;
use crate::arch::interrupt::TrapFrame;
use crate::arch::syscall::nr::SYS_SETRLIMIT;
use crate::process::resource::RLimit64;
use crate::process::syscall::sys_prlimit64::do_prlimit64;
use crate::process::ProcessManager;
use crate::syscall::table::FormattedSyscallParam;
use crate::syscall::table::Syscall;
use alloc::vec::Vec;
pub struct SysSetRlimit;
impl SysSetRlimit {
fn resource(args: &[usize]) -> usize {
args[0]
}
fn rlimit(args: &[usize]) -> *const RLimit64 {
args[1] as *const RLimit64
}
}
impl Syscall for SysSetRlimit {
fn num_args(&self) -> usize {
2
}
fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result<usize, SystemError> {
let resource = Self::resource(args);
let rlimit = Self::rlimit(args);
do_prlimit64(
ProcessManager::current_pcb().raw_pid(),
resource,
rlimit,
core::ptr::null_mut::<RLimit64>(),
)
}
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
vec![
FormattedSyscallParam::new("resource", format!("{:#x}", Self::resource(args))),
FormattedSyscallParam::new("rlimit", format!("{:#x}", Self::rlimit(args) as usize)),
]
}
}
syscall_table_macros::declare_syscall!(SYS_SETRLIMIT, SysSetRlimit);

View File

@ -477,8 +477,6 @@ impl Syscall {
let flags = args[4] as u32;
Self::sys_perf_event_open(attr, pid, cpu, group_fd, flags)
}
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
SYS_SETRLIMIT => Ok(0),
SYS_RT_SIGTIMEDWAIT => {
log::warn!("SYS_RT_SIGTIMEDWAIT has not yet been implemented");

View File

@ -0,0 +1,2 @@
# 暂时不支持该测例,因为/proc/sys/fs/nr_open没支持
RlimitTest.DupLimitedByNROpenSysctl

View File

@ -9,6 +9,7 @@ bad_test
uname_test
# 文件系统相关测试
dup_test
#stat_test
#chmod_test
#chown_test