mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 02:46:47 +00:00
Add dup,dup2 (#224)
* dup,dup2 * fix: sys_dup2语义与posix不一致的问题 --------- Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
parent
d7b31a969f
commit
2b771e32f5
@ -16,9 +16,10 @@ use crate::{
|
|||||||
ramfs::RamFS,
|
ramfs::RamFS,
|
||||||
vfs::{file::File, mount::MountFS, FileSystem, FileType},
|
vfs::{file::File, mount::MountFS, FileSystem, FileType},
|
||||||
},
|
},
|
||||||
include::bindings::bindings::{PAGE_4K_SIZE},
|
include::bindings::bindings::PAGE_4K_SIZE,
|
||||||
io::SeekFrom,
|
io::SeekFrom,
|
||||||
kerror, kinfo, syscall::SystemError,
|
kerror, kinfo,
|
||||||
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{file::FileMode, utils::rsplit_path, IndexNode, InodeId};
|
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
|
// 把文件对象存入pcb
|
||||||
return current_pcb().alloc_fd(file);
|
return current_pcb().alloc_fd(file, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。
|
/// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。
|
||||||
|
@ -3,14 +3,9 @@ use core::mem::MaybeUninit;
|
|||||||
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
|
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::asm::current::current_pcb,
|
arch::asm::current::current_pcb, driver::tty::TtyFilePrivateData,
|
||||||
driver::tty::TtyFilePrivateData,
|
filesystem::procfs::ProcfsFilePrivateData, include::bindings::bindings::process_control_block,
|
||||||
filesystem::procfs::ProcfsFilePrivateData,
|
io::SeekFrom, kerror, syscall::SystemError,
|
||||||
include::bindings::bindings::{
|
|
||||||
process_control_block,
|
|
||||||
},
|
|
||||||
io::SeekFrom,
|
|
||||||
kerror, syscall::SystemError,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Dirent, FileType, IndexNode, Metadata};
|
use super::{Dirent, FileType, IndexNode, Metadata};
|
||||||
|
@ -4,11 +4,14 @@ use alloc::{boxed::Box, string::ToString};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::asm::{current::current_pcb, ptrace::user_mode},
|
arch::asm::{current::current_pcb, ptrace::user_mode},
|
||||||
|
filesystem::vfs::file::FileDescriptorVec,
|
||||||
include::bindings::bindings::{
|
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,
|
io::SeekFrom,
|
||||||
kerror, syscall::SystemError,
|
kerror,
|
||||||
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -50,7 +50,7 @@ use mm::allocator::KernelAllocator;
|
|||||||
// <3>
|
// <3>
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::asm::current::current_pcb,
|
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分配器
|
// 声明全局的slab分配器
|
||||||
@ -97,6 +97,5 @@ pub fn panic(info: &PanicInfo) -> ! {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn __rust_demo_func() -> i32 {
|
pub extern "C" fn __rust_demo_func() -> i32 {
|
||||||
printk_color!(GREEN, BLACK, "__rust_demo_func()\n");
|
printk_color!(GREEN, BLACK, "__rust_demo_func()\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,17 @@ use alloc::boxed::Box;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{asm::current::current_pcb, fpu::FpState},
|
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::{
|
include::bindings::bindings::{
|
||||||
process_control_block, CLONE_FS, PROC_INTERRUPTIBLE,
|
process_control_block, CLONE_FS, PROC_INTERRUPTIBLE, PROC_RUNNING, PROC_STOPPED,
|
||||||
PROC_RUNNING, PROC_STOPPED, PROC_UNINTERRUPTIBLE,
|
PROC_UNINTERRUPTIBLE,
|
||||||
},
|
},
|
||||||
sched::core::{cpu_executing, sched_enqueue},
|
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};
|
use super::preempt::{preempt_disable, preempt_enable};
|
||||||
@ -173,9 +177,12 @@ impl process_control_block {
|
|||||||
|
|
||||||
/// @brief 申请文件描述符,并把文件对象存入其中。
|
/// @brief 申请文件描述符,并把文件对象存入其中。
|
||||||
///
|
///
|
||||||
|
/// @param file 要存放的文件对象
|
||||||
|
/// @param fd 如果为Some(i32),表示指定要申请这个文件描述符,如果这个文件描述符已经被使用,那么返回EBADF
|
||||||
|
///
|
||||||
/// @return Ok(i32) 申请到的文件描述符编号
|
/// @return Ok(i32) 申请到的文件描述符编号
|
||||||
/// @return Err(SystemError) 申请失败,返回错误码,并且,file对象将被drop掉
|
/// @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的文件描述符数组的引用
|
// 获取pcb的文件描述符数组的引用
|
||||||
let fds: &mut FileDescriptorVec =
|
let fds: &mut FileDescriptorVec =
|
||||||
if let Some(f) = FileDescriptorVec::from_pcb(current_pcb()) {
|
if let Some(f) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||||
@ -192,16 +199,28 @@ impl process_control_block {
|
|||||||
r.unwrap()
|
r.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
// 寻找空闲的文件描述符
|
if fd.is_some() {
|
||||||
let mut cnt = 0;
|
// 指定了要申请的文件描述符编号
|
||||||
for x in fds.fds.iter_mut() {
|
let new_fd = fd.unwrap();
|
||||||
|
let x = &mut fds.fds[new_fd as usize];
|
||||||
if x.is_none() {
|
if x.is_none() {
|
||||||
*x = Some(Box::new(file));
|
*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 根据文件描述符序号,获取文件结构体的可变引用
|
/// @brief 根据文件描述符序号,获取文件结构体的可变引用
|
||||||
@ -377,10 +396,10 @@ pub fn init_stdio() -> Result<(), SystemError> {
|
|||||||
.expect("Init stdio: can't create stderr");
|
.expect("Init stdio: can't create stderr");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
按照规定,进程的文件描述符数组的前三个位置,分别是stdin, stdout, stderr
|
按照规定,进程的文件描述符数组的前三个位置,分别是stdin, stdout, stderr
|
||||||
*/
|
*/
|
||||||
assert_eq!(current_pcb().alloc_fd(stdin).unwrap(), 0);
|
assert_eq!(current_pcb().alloc_fd(stdin, None).unwrap(), 0);
|
||||||
assert_eq!(current_pcb().alloc_fd(stdout).unwrap(), 1);
|
assert_eq!(current_pcb().alloc_fd(stdout, None).unwrap(), 1);
|
||||||
assert_eq!(current_pcb().alloc_fd(stderr).unwrap(), 2);
|
assert_eq!(current_pcb().alloc_fd(stderr, None).unwrap(), 2);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -400,6 +400,9 @@ uint64_t sys_pipe(struct pt_regs *regs)
|
|||||||
|
|
||||||
extern uint64_t sys_mkdir(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] = {
|
system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = {
|
||||||
[0] = system_call_not_exists,
|
[0] = system_call_not_exists,
|
||||||
[1] = sys_put_string,
|
[1] = sys_put_string,
|
||||||
@ -429,5 +432,7 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = {
|
|||||||
[25] = sys_rt_sigreturn,
|
[25] = sys_rt_sigreturn,
|
||||||
[26] = sys_getpid,
|
[26] = sys_getpid,
|
||||||
[27] = sys_sched,
|
[27] = sys_sched,
|
||||||
[28 ... 255] = system_call_not_exists,
|
[28] = sys_dup,
|
||||||
|
[29] = sys_dup2,
|
||||||
|
[30 ... 255] = system_call_not_exists,
|
||||||
};
|
};
|
||||||
|
@ -39,5 +39,7 @@
|
|||||||
#define SYS_RT_SIGRETURN 25 // 从信号处理函数返回
|
#define SYS_RT_SIGRETURN 25 // 从信号处理函数返回
|
||||||
#define SYS_GETPID 26 // 获取当前进程的pid(进程标识符)
|
#define SYS_GETPID 26 // 获取当前进程的pid(进程标识符)
|
||||||
#define SYS_SCHED 27 // 让系统立即运行调度器(该系统调用不能由运行在Ring3的程序发起)
|
#define SYS_SCHED 27 // 让系统立即运行调度器(该系统调用不能由运行在Ring3的程序发起)
|
||||||
|
#define SYS_DUP 28
|
||||||
|
#define SYS_DUP2 29
|
||||||
|
|
||||||
#define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用
|
#define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用
|
@ -1,10 +1,10 @@
|
|||||||
#include "sys_version.h" // 这是系统的版本头文件,在编译过程中自动生成
|
#include "sys_version.h" // 这是系统的版本头文件,在编译过程中自动生成
|
||||||
|
#include <fcntl.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
void print_ascii_logo()
|
void print_ascii_logo()
|
||||||
{
|
{
|
||||||
printf(" ____ ___ ____ \n");
|
printf(" ____ ___ ____ \n");
|
||||||
|
@ -122,6 +122,10 @@ void swab(void *restrict src, void *restrict dest, ssize_t nbytes);
|
|||||||
|
|
||||||
pid_t getpid(void);
|
pid_t getpid(void);
|
||||||
|
|
||||||
|
int dup(int fd);
|
||||||
|
|
||||||
|
int dup2(int ofd, int nfd);
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <libsystem/syscall.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <libsystem/syscall.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 关闭文件接口
|
* @brief 关闭文件接口
|
||||||
@ -88,7 +88,6 @@ pid_t vfork(void)
|
|||||||
uint64_t brk(uint64_t end_brk)
|
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);
|
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;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,5 +201,15 @@ void swab(void *restrict src, void *restrict dest, ssize_t nbytes)
|
|||||||
*/
|
*/
|
||||||
pid_t getpid(void)
|
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);
|
||||||
}
|
}
|
@ -32,6 +32,8 @@
|
|||||||
#define SYS_SIGACTION 24 // 设置进程的信号处理动作
|
#define SYS_SIGACTION 24 // 设置进程的信号处理动作
|
||||||
#define SYS_RT_SIGRETURN 25 // 从信号处理函数返回
|
#define SYS_RT_SIGRETURN 25 // 从信号处理函数返回
|
||||||
#define SYS_GETPID 26 // 获取当前进程的pid(进程标识符)
|
#define SYS_GETPID 26 // 获取当前进程的pid(进程标识符)
|
||||||
|
#define SYS_DUP 28
|
||||||
|
#define SYS_DUP2 29
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 用户态系统调用函数
|
* @brief 用户态系统调用函数
|
||||||
|
Loading…
x
Reference in New Issue
Block a user