Skip to content

Commit

Permalink
新增系统调用,并对照linux-6.1.9改写sys_wait4 (DragonOS-Community#440)
Browse files Browse the repository at this point in the history
* 1. 新增以下系统调用
            - SYS_LSTAT
            - SYS_READV
            - SYS_ACCESS
            - SYS_UNLINK
            - SYS_CHMOD
            - SYS_FCHMOD
            - SYS_UMASK
            - SYS_SYSINFO
            - SYS_CLOCK_GETTIME
            - SYS_FCHMODAT
            - SYS_FACCESSAT

2. 修改sys_wait4,使得其部分符合Linux的行为(还是有些地方不符合的,详情请对比linux-6.1.9的sys_wait4接口)
  • Loading branch information
fslongjin authored and yuyi2439 committed Nov 14, 2023
1 parent 96b76db commit 6fbace6
Show file tree
Hide file tree
Showing 19 changed files with 735 additions and 167 deletions.
36 changes: 36 additions & 0 deletions kernel/src/arch/x86_64/ipc/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,42 @@ bitflags! {
}
}

/// SIGCHLD si_codes
#[derive(Debug, Clone, Copy, PartialEq, Eq, ToPrimitive)]
#[allow(dead_code)]
pub enum SigChildCode {
/// child has exited
///
/// CLD_EXITED
Exited = 1,
/// child was killed
///
/// CLD_KILLED
Killed = 2,
/// child terminated abnormally
///
/// CLD_DUMPED
Dumped = 3,
/// traced child has trapped
///
/// CLD_TRAPPED
Trapped = 4,
/// child has stopped
///
/// CLD_STOPPED
Stopped = 5,
/// stopped child has continued
///
/// CLD_CONTINUED
Continued = 6,
}

impl Into<i32> for SigChildCode {
fn into(self) -> i32 {
self as i32
}
}

#[repr(C, align(16))]
#[derive(Debug, Clone, Copy)]
pub struct SigFrame {
Expand Down
13 changes: 7 additions & 6 deletions kernel/src/arch/x86_64/process/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,16 @@ impl Syscall {
envp: Vec<String>,
regs: &mut TrapFrame,
) -> Result<(), SystemError> {
// kdebug!(
// "tmp_rs_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
// 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
let pcb = ProcessManager::current_pcb();
// crate::kdebug!(
// "pid: {:?} do_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
// pcb.pid(),
// path,
// argv,
// envp
// );
// 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
let pcb = ProcessManager::current_pcb();

let mut basic_info = pcb.basic_mut();
// 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free)
Expand Down Expand Up @@ -109,7 +110,7 @@ impl Syscall {

// kdebug!("regs: {:?}\n", regs);

// kdebug!(
// crate::kdebug!(
// "tmp_rs_execve: done, load_result.entry_point()={:?}",
// load_result.entry_point()
// );
Expand Down
40 changes: 36 additions & 4 deletions kernel/src/arch/x86_64/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,25 @@ use crate::{
ipc::signal_types::SignalArch,
libs::align::SafeForZero,
mm::VirtAddr,
process::ProcessManager,
syscall::{Syscall, SystemError, SYS_RT_SIGRETURN},
};
use alloc::string::String;

use super::{interrupt::TrapFrame, mm::barrier::mfence};

pub const SYS_LSTAT: usize = 6;
pub const SYS_READV: usize = 19;
pub const SYS_ACCESS: usize = 21;
pub const SYS_PRLIMIT64: usize = 302;
pub const SYS_UNLINK: usize = 87;
pub const SYS_CHMOD: usize = 90;
pub const SYS_FCHMOD: usize = 91;
pub const SYS_UMASK: usize = 95;
pub const SYS_SYSINFO: usize = 99;
pub const SYS_CLOCK_GETTIME: usize = 228;
pub const SYS_FCHMODAT: usize = 268;
pub const SYS_FACCESSAT: usize = 269;
pub const SYS_PRLIMIT64: usize = 302;
pub const SYS_FACCESSAT2: usize = 439;

/// ### 存储PCB系统调用栈以及在syscall过程中暂存用户态rsp的结构体
Expand Down Expand Up @@ -44,9 +54,15 @@ extern "C" {
}

macro_rules! syscall_return {
($val:expr, $regs:expr) => {{
($val:expr, $regs:expr, $show:expr) => {{
let ret = $val;
$regs.rax = ret as u64;

if $show {
let pid = ProcessManager::current_pcb().pid();
crate::kdebug!("syscall return:pid={:?},ret= {:?}\n", pid, ret as isize);
}

unsafe {
CurrentIrqArch::interrupt_disable();
}
Expand All @@ -69,18 +85,34 @@ pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) -> () {
frame.r9 as usize,
];
mfence();
let pid = ProcessManager::current_pcb().pid();
let show = false;
// let show = if syscall_num != SYS_SCHED && pid.data() > 3 {
// true
// } else {
// false
// };

if show {
crate::kdebug!("syscall: pid: {:?}, num={:?}\n", pid, syscall_num);
}

// Arch specific syscall
match syscall_num {
SYS_RT_SIGRETURN => {
syscall_return!(X86_64SignalArch::sys_rt_sigreturn(frame) as usize, frame);
syscall_return!(
X86_64SignalArch::sys_rt_sigreturn(frame) as usize,
frame,
show
);
}
_ => {}
}
syscall_return!(
Syscall::handle(syscall_num, &args, frame).unwrap_or_else(|e| e.to_posix_errno() as usize)
as u64,
frame
frame,
show
);
}

Expand Down
30 changes: 22 additions & 8 deletions kernel/src/filesystem/vfs/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@ use crate::{
vfs::{mount::MountFS, syscall::ModeType, AtomicInodeId, FileSystem, FileType},
},
kdebug, kerror, kinfo,
process::ProcessManager,
syscall::SystemError,
};

use super::{file::FileMode, utils::rsplit_path, IndexNode, InodeId, MAX_PATHLEN};
use super::{
file::FileMode,
utils::{rsplit_path, user_path_at},
IndexNode, InodeId, MAX_PATHLEN, VFS_MAX_FOLLOW_SYMLINK_TIMES,
};

/// @brief 原子地生成新的Inode号。
/// 请注意,所有的inode号都需要通过该函数来生成.全局的inode号,除了以下两个特殊的以外,都是唯一的
Expand Down Expand Up @@ -206,13 +211,17 @@ pub fn do_mkdir(path: &str, _mode: FileMode) -> Result<u64, SystemError> {
}

/// @brief 删除文件夹
pub fn do_remove_dir(path: &str) -> Result<u64, SystemError> {
pub fn do_remove_dir(dirfd: i32, path: &str) -> Result<u64, SystemError> {
// 文件名过长
if path.len() > MAX_PATHLEN as usize {
return Err(SystemError::ENAMETOOLONG);
}

let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
let pcb = ProcessManager::current_pcb();
let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path.to_string())?;

let inode: Result<Arc<dyn IndexNode>, SystemError> =
inode_begin.lookup_follow_symlink(remain_path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES);

if inode.is_err() {
let errno = inode.unwrap_err();
Expand All @@ -222,9 +231,10 @@ pub fn do_remove_dir(path: &str) -> Result<u64, SystemError> {
}
}

let (filename, parent_path) = rsplit_path(path);
let (filename, parent_path) = rsplit_path(&remain_path);
// 查找父目录
let parent_inode: Arc<dyn IndexNode> = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
let parent_inode: Arc<dyn IndexNode> = inode_begin
.lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;

if parent_inode.metadata()?.file_type != FileType::Dir {
return Err(SystemError::ENOTDIR);
Expand All @@ -242,13 +252,16 @@ pub fn do_remove_dir(path: &str) -> Result<u64, SystemError> {
}

/// @brief 删除文件
pub fn do_unlink_at(path: &str, _mode: FileMode) -> Result<u64, SystemError> {
pub fn do_unlink_at(dirfd: i32, path: &str) -> Result<u64, SystemError> {
// 文件名过长
if path.len() > MAX_PATHLEN as usize {
return Err(SystemError::ENAMETOOLONG);
}
let pcb = ProcessManager::current_pcb();
let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path.to_string())?;

let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
let inode: Result<Arc<dyn IndexNode>, SystemError> =
inode_begin.lookup_follow_symlink(&remain_path, VFS_MAX_FOLLOW_SYMLINK_TIMES);

if inode.is_err() {
let errno = inode.clone().unwrap_err();
Expand All @@ -264,7 +277,8 @@ pub fn do_unlink_at(path: &str, _mode: FileMode) -> Result<u64, SystemError> {

let (filename, parent_path) = rsplit_path(path);
// 查找父目录
let parent_inode: Arc<dyn IndexNode> = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
let parent_inode: Arc<dyn IndexNode> = inode_begin
.lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;

if parent_inode.metadata()?.file_type != FileType::Dir {
return Err(SystemError::ENOTDIR);
Expand Down
3 changes: 3 additions & 0 deletions kernel/src/filesystem/vfs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};

/// 文件私有信息的枚举类型
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub enum FilePrivateData {
/// 管道文件私有信息
Pipefs(PipeFsPrivateData),
Expand Down Expand Up @@ -198,6 +199,7 @@ impl File {
}

/// @brief 根据inode号获取子目录项的名字
#[allow(dead_code)]
pub fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> {
return self.inode.get_entry_name(ino);
}
Expand Down Expand Up @@ -535,6 +537,7 @@ impl FileDescriptorVec {
return Ok(());
}

#[allow(dead_code)]
pub fn iter(&self) -> FileDescriptorIterator {
return FileDescriptorIterator::new(self);
}
Expand Down
6 changes: 4 additions & 2 deletions kernel/src/filesystem/vfs/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![allow(dead_code)]

pub mod core;
pub mod fcntl;
pub mod file;
Expand Down Expand Up @@ -50,6 +48,7 @@ pub enum FileType {
Socket,
}

#[allow(dead_code)]
#[derive(Debug, Clone)]
pub enum SpecialNodeData {
/// 管道文件
Expand All @@ -62,6 +61,7 @@ pub enum SpecialNodeData {

/* these are defined by POSIX and also present in glibc's dirent.h */
/// 完整含义请见 http://www.gnu.org/software/libc/manual/html_node/Directory-Entries.html
#[allow(dead_code)]
pub const DT_UNKNOWN: u16 = 0;
/// 命名管道,或者FIFO
pub const DT_FIFO: u16 = 1;
Expand All @@ -78,7 +78,9 @@ pub const DT_LNK: u16 = 10;
// 是一个socket
pub const DT_SOCK: u16 = 12;
// 这个是抄Linux的,还不知道含义
#[allow(dead_code)]
pub const DT_WHT: u16 = 14;
#[allow(dead_code)]
pub const DT_MAX: u16 = 16;

/// vfs容许的最大的符号链接跳转次数
Expand Down
45 changes: 40 additions & 5 deletions kernel/src/filesystem/vfs/open.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
use crate::syscall::SystemError;
use crate::{
process::ProcessManager,
syscall::{user_access::check_and_clone_cstr, SystemError},
};

use super::{fcntl::AtFlags, syscall::ModeType};
use super::{
fcntl::AtFlags, syscall::ModeType, utils::user_path_at, MAX_PATHLEN,
VFS_MAX_FOLLOW_SYMLINK_TIMES,
};

pub(super) fn do_faccessat(
_dirfd: i32,
_pathname: *const u8,
dirfd: i32,
path: *const u8,
mode: ModeType,
flags: u32,
) -> Result<usize, SystemError> {
if (mode.bits() & (!ModeType::S_IXUGO.bits())) != 0 {
if (mode.bits() & (!ModeType::S_IRWXO.bits())) != 0 {
return Err(SystemError::EINVAL);
}

Expand All @@ -22,6 +28,35 @@ pub(super) fn do_faccessat(

// let follow_symlink = flags & AtFlags::AT_SYMLINK_NOFOLLOW.bits() as u32 == 0;

let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;

if path.len() == 0 {
return Err(SystemError::EINVAL);
}

let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;

// 如果找不到文件,则返回错误码ENOENT
let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;

// todo: 接着完善(可以借鉴linux 6.1.9的do_faccessat)
return Ok(0);
}

pub fn do_fchmodat(dirfd: i32, path: *const u8, _mode: ModeType) -> Result<usize, SystemError> {
let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;

if path.len() == 0 {
return Err(SystemError::EINVAL);
}

let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;

// 如果找不到文件,则返回错误码ENOENT
let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;

kwarn!("do_fchmodat: not implemented yet\n");
// todo: 真正去改变文件的权限

return Ok(0);
}

0 comments on commit 6fbace6

Please sign in to comment.