mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +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,
|
||||
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的长度相同。
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(());
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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的系统调用
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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 用户态系统调用函数
|
||||
|
Loading…
x
Reference in New Issue
Block a user