Add dup,dup2 (#224)

* dup,dup2

* fix: sys_dup2语义与posix不一致的问题

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
Gou Ngai 2023-04-02 15:43:53 +08:00 committed by GitHub
parent d7b31a969f
commit 2b771e32f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 166 additions and 39 deletions

View File

@ -16,9 +16,10 @@ use crate::{
ramfs::RamFS,
vfs::{file::File, mount::MountFS, FileSystem, FileType},
},
include::bindings::bindings::{PAGE_4K_SIZE},
include::bindings::bindings::PAGE_4K_SIZE,
io::SeekFrom,
kerror, kinfo, syscall::SystemError,
kerror, kinfo,
syscall::SystemError,
};
use super::{file::FileMode, utils::rsplit_path, IndexNode, InodeId};
@ -237,7 +238,7 @@ pub fn do_open(path: &str, mode: FileMode) -> Result<i32, SystemError> {
}
// 把文件对象存入pcb
return current_pcb().alloc_fd(file);
return current_pcb().alloc_fd(file, None);
}
/// @brief 根据文件描述符读取文件数据。尝试读取的数据长度与buf的长度相同。

View File

@ -3,14 +3,9 @@ use core::mem::MaybeUninit;
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
use crate::{
arch::asm::current::current_pcb,
driver::tty::TtyFilePrivateData,
filesystem::procfs::ProcfsFilePrivateData,
include::bindings::bindings::{
process_control_block,
},
io::SeekFrom,
kerror, syscall::SystemError,
arch::asm::current::current_pcb, driver::tty::TtyFilePrivateData,
filesystem::procfs::ProcfsFilePrivateData, include::bindings::bindings::process_control_block,
io::SeekFrom, kerror, syscall::SystemError,
};
use super::{Dirent, FileType, IndexNode, Metadata};

View File

@ -4,11 +4,14 @@ use alloc::{boxed::Box, string::ToString};
use crate::{
arch::asm::{current::current_pcb, ptrace::user_mode},
filesystem::vfs::file::FileDescriptorVec,
include::bindings::bindings::{
pt_regs, verify_area, AT_REMOVEDIR, PAGE_2M_SIZE, PAGE_4K_SIZE, PROC_MAX_FD_NUM, SEEK_CUR, SEEK_END, SEEK_MAX, SEEK_SET,
pt_regs, verify_area, AT_REMOVEDIR, PAGE_2M_SIZE, PAGE_4K_SIZE, PROC_MAX_FD_NUM, SEEK_CUR,
SEEK_END, SEEK_MAX, SEEK_SET,
},
io::SeekFrom,
kerror, syscall::SystemError,
kerror,
syscall::SystemError,
};
use super::{
@ -344,3 +347,91 @@ pub extern "C" fn sys_unlink_at(regs: &pt_regs) -> u64 {
}
}
}
fn do_dup(oldfd: i32) -> Result<i32, SystemError> {
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
// 获得当前文件描述符数组
// 确认oldfd是否有效
if FileDescriptorVec::validate_fd(oldfd) {
if let Some(file) = &fds.fds[oldfd as usize] {
// 尝试获取对应的文件结构体
let file_cp = (file).try_clone();
if file_cp.is_none() {
return Err(SystemError::EBADF);
}
let res = current_pcb().alloc_fd(*file_cp.unwrap(), None);
// 申请文件描述符,并把文件对象存入其中
return res;
}
// oldfd对应的文件不存在
return Err(SystemError::EBADF);
}
return Err(SystemError::EBADF);
} else {
return Err(SystemError::EMFILE);
}
}
#[no_mangle]
/// @brief 根据提供的文件描述符的fd复制对应的文件结构体并返回新复制的文件结构体对应的fd
pub extern "C" fn sys_dup(regs: &pt_regs) -> u64 {
let fd: i32 = regs.r8 as i32;
let r = do_dup(fd);
if r.is_ok() {
return r.unwrap() as u64;
} else {
return r.unwrap_err().to_posix_errno() as u64;
}
}
fn do_dup2(oldfd: i32, newfd: i32) -> Result<i32, SystemError> {
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
// 获得当前文件描述符数组
if FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd) {
//确认oldfd, newid是否有效
if oldfd == newfd {
// 若oldfd与newfd相等
return Ok(newfd);
}
if let Some(file) = &fds.fds[oldfd as usize] {
if fds.fds[newfd as usize].is_some() {
// close newfd
if let Err(_) = current_pcb().drop_fd(newfd) {
// An I/O error occurred while attempting to close fildes2.
return Err(SystemError::EIO);
}
}
// 尝试获取对应的文件结构体
let file_cp = file.try_clone();
if file_cp.is_none() {
return Err(SystemError::EBADF);
}
// 申请文件描述符,并把文件对象存入其中
let res = current_pcb().alloc_fd(*file_cp.unwrap(), Some(newfd));
return res;
}
return Err(SystemError::EBADF);
} else {
return Err(SystemError::EBADF);
}
}
// 从pcb获取文件描述符数组失败
return Err(SystemError::EMFILE);
}
#[no_mangle]
/// @brief 根据提供的文件描述符的fd和指定新fd复制对应的文件结构体
/// 并返回新复制的文件结构体对应的fd
pub extern "C" fn sys_dup2(regs: &pt_regs) -> u64 {
let ofd = regs.r8 as i32;
let nfd = regs.r9 as i32;
let r = do_dup2(ofd, nfd);
if r.is_ok() {
return r.unwrap() as u64;
} else {
return r.unwrap_err().to_posix_errno() as u64;
}
}

View File

@ -50,7 +50,7 @@ use mm::allocator::KernelAllocator;
// <3>
use crate::{
arch::asm::current::current_pcb,
include::bindings::bindings::{process_do_exit, BLACK, GREEN}, filesystem::vfs::ROOT_INODE,
include::bindings::bindings::{process_do_exit, BLACK, GREEN},
};
// 声明全局的slab分配器
@ -97,6 +97,5 @@ pub fn panic(info: &PanicInfo) -> ! {
#[no_mangle]
pub extern "C" fn __rust_demo_func() -> i32 {
printk_color!(GREEN, BLACK, "__rust_demo_func()\n");
return 0;
}

View File

@ -7,13 +7,17 @@ use alloc::boxed::Box;
use crate::{
arch::{asm::current::current_pcb, fpu::FpState},
filesystem::vfs::{file::{File, FileDescriptorVec, FileMode}, ROOT_INODE},
filesystem::vfs::{
file::{File, FileDescriptorVec, FileMode},
ROOT_INODE,
},
include::bindings::bindings::{
process_control_block, CLONE_FS, PROC_INTERRUPTIBLE,
PROC_RUNNING, PROC_STOPPED, PROC_UNINTERRUPTIBLE,
process_control_block, CLONE_FS, PROC_INTERRUPTIBLE, PROC_RUNNING, PROC_STOPPED,
PROC_UNINTERRUPTIBLE,
},
sched::core::{cpu_executing, sched_enqueue},
smp::core::{smp_get_processor_id, smp_send_reschedule}, syscall::SystemError,
smp::core::{smp_get_processor_id, smp_send_reschedule},
syscall::SystemError,
};
use super::preempt::{preempt_disable, preempt_enable};
@ -173,9 +177,12 @@ impl process_control_block {
/// @brief 申请文件描述符,并把文件对象存入其中。
///
/// @param file 要存放的文件对象
/// @param fd 如果为Some(i32)表示指定要申请这个文件描述符如果这个文件描述符已经被使用那么返回EBADF
///
/// @return Ok(i32) 申请到的文件描述符编号
/// @return Err(SystemError) 申请失败返回错误码并且file对象将被drop掉
pub fn alloc_fd(&mut self, file: File) -> Result<i32, SystemError> {
pub fn alloc_fd(&mut self, file: File, fd: Option<i32>) -> Result<i32, SystemError> {
// 获取pcb的文件描述符数组的引用
let fds: &mut FileDescriptorVec =
if let Some(f) = FileDescriptorVec::from_pcb(current_pcb()) {
@ -192,16 +199,28 @@ impl process_control_block {
r.unwrap()
};
// 寻找空闲的文件描述符
let mut cnt = 0;
for x in fds.fds.iter_mut() {
if fd.is_some() {
// 指定了要申请的文件描述符编号
let new_fd = fd.unwrap();
let x = &mut fds.fds[new_fd as usize];
if x.is_none() {
*x = Some(Box::new(file));
return Ok(cnt);
return Ok(new_fd);
} else {
return Err(SystemError::EBADF);
}
cnt += 1;
} else {
// 寻找空闲的文件描述符
let mut cnt = 0;
for x in fds.fds.iter_mut() {
if x.is_none() {
*x = Some(Box::new(file));
return Ok(cnt);
}
cnt += 1;
}
return Err(SystemError::ENFILE);
}
return Err(SystemError::ENFILE);
}
/// @brief 根据文件描述符序号,获取文件结构体的可变引用
@ -377,10 +396,10 @@ pub fn init_stdio() -> Result<(), SystemError> {
.expect("Init stdio: can't create stderr");
/*
stdin, stdout, stderr
*/
assert_eq!(current_pcb().alloc_fd(stdin).unwrap(), 0);
assert_eq!(current_pcb().alloc_fd(stdout).unwrap(), 1);
assert_eq!(current_pcb().alloc_fd(stderr).unwrap(), 2);
stdin, stdout, stderr
*/
assert_eq!(current_pcb().alloc_fd(stdin, None).unwrap(), 0);
assert_eq!(current_pcb().alloc_fd(stdout, None).unwrap(), 1);
assert_eq!(current_pcb().alloc_fd(stderr, None).unwrap(), 2);
return Ok(());
}

View File

@ -400,6 +400,9 @@ uint64_t sys_pipe(struct pt_regs *regs)
extern uint64_t sys_mkdir(struct pt_regs *regs);
extern int sys_dup(int oldfd);
extern int sys_dup2(int oldfd, int newfd);
system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = {
[0] = system_call_not_exists,
[1] = sys_put_string,
@ -429,5 +432,7 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = {
[25] = sys_rt_sigreturn,
[26] = sys_getpid,
[27] = sys_sched,
[28 ... 255] = system_call_not_exists,
[28] = sys_dup,
[29] = sys_dup2,
[30 ... 255] = system_call_not_exists,
};

View File

@ -39,5 +39,7 @@
#define SYS_RT_SIGRETURN 25 // 从信号处理函数返回
#define SYS_GETPID 26 // 获取当前进程的pid进程标识符
#define SYS_SCHED 27 // 让系统立即运行调度器该系统调用不能由运行在Ring3的程序发起
#define SYS_DUP 28
#define SYS_DUP2 29
#define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用

View File

@ -1,10 +1,10 @@
#include "sys_version.h" // 这是系统的版本头文件,在编译过程中自动生成
#include "sys_version.h" // 这是系统的版本头文件,在编译过程中自动生成
#include <fcntl.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
void print_ascii_logo()
{
printf(" ____ ___ ____ \n");
@ -36,7 +36,7 @@ void print_copyright()
}
int main()
{
{
print_ascii_logo();
print_copyright();

View File

@ -122,6 +122,10 @@ void swab(void *restrict src, void *restrict dest, ssize_t nbytes);
pid_t getpid(void);
int dup(int fd);
int dup2(int ofd, int nfd);
#if defined(__cplusplus)
} /* extern "C" */
#endif

View File

@ -1,10 +1,10 @@
#include <errno.h>
#include <fcntl.h>
#include <libsystem/syscall.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <libsystem/syscall.h>
/**
* @brief
@ -88,7 +88,6 @@ pid_t vfork(void)
uint64_t brk(uint64_t end_brk)
{
uint64_t x = (uint64_t)syscall_invoke(SYS_BRK, (uint64_t)end_brk, 0, 0, 0, 0, 0, 0, 0);
// printf("brk(): end_brk=%#018lx x=%#018lx", (uint64_t)end_brk, x);
return x;
}
@ -197,10 +196,20 @@ void swab(void *restrict src, void *restrict dest, ssize_t nbytes)
/**
* @brief pid
*
*
* @return pid_t pid
*/
pid_t getpid(void)
{
syscall_invoke(SYS_GETPID, 0, 0, 0, 0, 0, 0, 0, 0);
return syscall_invoke(SYS_GETPID, 0, 0, 0, 0, 0, 0, 0, 0);
}
int dup(int fd)
{
return syscall_invoke(SYS_DUP, fd, 0, 0, 0, 0, 0, 0, 0);
}
int dup2(int ofd, int nfd)
{
return syscall_invoke(SYS_DUP2, ofd, nfd, 0, 0, 0, 0, 0, 0);
}

View File

@ -32,6 +32,8 @@
#define SYS_SIGACTION 24 // 设置进程的信号处理动作
#define SYS_RT_SIGRETURN 25 // 从信号处理函数返回
#define SYS_GETPID 26 // 获取当前进程的pid进程标识符
#define SYS_DUP 28
#define SYS_DUP2 29
/**
* @brief