From 5be90ccccd441b1a38dbbf4fc99c7375cede8d8d Mon Sep 17 00:00:00 2001 From: Minep Date: Sun, 31 Jul 2022 17:15:38 +0100 Subject: [PATCH 1/1] feat: implement dup(2), dup2(2) fix: free & copy the fd tables upon process destoryed or forked --- README.md | 4 +- lunaix-os/includes/lunaix/fs.h | 1 + lunaix-os/includes/lunaix/lunistd.h | 6 +++ lunaix-os/includes/lunaix/syscall.h | 6 ++- lunaix-os/kernel/asm/x86/syscall.S | 2 + lunaix-os/kernel/fs/vfs.c | 61 +++++++++++++++++++++++++++-- lunaix-os/kernel/process.c | 1 + lunaix-os/kernel/sched.c | 8 ++++ 8 files changed, 84 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index de08a2e..b9a96dc 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ LunaixOS - 一个简单的,详细的,POSIX兼容的(但愿!),带有 + 内存管理与按需分页(Demand Paging) + 键盘输入 + 多进程 -+ 31个常见的Linux/POSIX系统调用([附录1](#appendix1)) ++ 33个常见的Linux/POSIX系统调用([附录1](#appendix1)) + 用户模式 + 信号机制 + PCI 3.0 @@ -180,6 +180,8 @@ qemu-img create -f vdi machine/disk1.vdi 128M 2. `unlinkat(2)` 2. `link(2)` 2. `fsync(2)` +2. `dup(2)` +2. `dup2(2)` ### LunaixOS自有 diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index d233ff0..43a5cf4 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -101,6 +101,7 @@ struct v_fd { struct v_file* file; int pos; + int flags; }; struct v_inode diff --git a/lunaix-os/includes/lunaix/lunistd.h b/lunaix-os/includes/lunaix/lunistd.h index 9095c37..472f638 100644 --- a/lunaix-os/includes/lunaix/lunistd.h +++ b/lunaix-os/includes/lunaix/lunistd.h @@ -41,4 +41,10 @@ __LXSYSCALL1(int, unlink, const char*, pathname) __LXSYSCALL1(int, close, int, fd) +__LXSYSCALL2(int, dup2, int, oldfd, int, newfd) + +__LXSYSCALL1(int, dup, int, oldfd) + +__LXSYSCALL1(int, fsync, int, fildes) + #endif /* __LUNAIX_UNISTD_H */ diff --git a/lunaix-os/includes/lunaix/syscall.h b/lunaix-os/includes/lunaix/syscall.h index 82986ab..30941f6 100644 --- a/lunaix-os/includes/lunaix/syscall.h +++ b/lunaix-os/includes/lunaix/syscall.h @@ -13,6 +13,7 @@ #define __SYSCALL__exit 8 #define __SYSCALL_wait 9 #define __SYSCALL_waitpid 10 + #define __SYSCALL_sigreturn 11 #define __SYSCALL_sigprocmask 12 #define __SYSCALL_signal 13 @@ -21,9 +22,9 @@ #define __SYSCALL_alarm 16 #define __SYSCALL_sigpending 17 #define __SYSCALL_sigsuspend 18 - #define __SYSCALL_open 19 #define __SYSCALL_close 20 + #define __SYSCALL_read 21 #define __SYSCALL_write 22 #define __SYSCALL_readdir 23 @@ -33,10 +34,13 @@ #define __SYSCALL_readlink 27 #define __SYSCALL_readlinkat 28 #define __SYSCALL_rmdir 29 + #define __SYSCALL_unlink 30 #define __SYSCALL_unlinkat 31 #define __SYSCALL_link 32 #define __SYSCALL_fsync 33 +#define __SYSCALL_dup 34 +#define __SYSCALL_dup2 35 #define __SYSCALL_MAX 0x100 diff --git a/lunaix-os/kernel/asm/x86/syscall.S b/lunaix-os/kernel/asm/x86/syscall.S index be5660f..ae63117 100644 --- a/lunaix-os/kernel/asm/x86/syscall.S +++ b/lunaix-os/kernel/asm/x86/syscall.S @@ -41,6 +41,8 @@ .long __lxsys_unlinkat .long __lxsys_link .long __lxsys_fsync + .long __lxsys_dup + .long __lxsys_dup2 2: .rept __SYSCALL_MAX - (2b - 1b)/4 .long 0 diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index de08cec..05741d8 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -478,9 +478,8 @@ __DEFINE_LXSYSCALL2(int, open, const char*, path, int, options) return DO_STATUS(errno); } - -#define GET_FD(fd, fd_s) \ - (fd >= 0 && fd < VFS_MAX_FD && (fd_s = __current->fdtable->fds[fd])) +#define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD) +#define GET_FD(fd, fd_s) (TEST_FD(fd) && (fd_s = __current->fdtable->fds[fd])) __DEFINE_LXSYSCALL1(int, close, int, fd) { @@ -813,5 +812,61 @@ __DEFINE_LXSYSCALL1(int, fsync, int, fildes) errno = vfs_fsync(fd_s->file); } + return DO_STATUS(errno); +} + +int +__vfs_dup_fd(struct v_fd* old, struct v_fd** new) +{ + int errno = 0; + struct v_file* newopened; + if (!(errno = vfs_open(old->file->dnode, &newopened))) { + *new = cake_grab(fd_pile); + **new = (struct v_fd){ .file = newopened, + .pos = old->pos, + .flags = old->flags }; + } + + return errno; +} + +__DEFINE_LXSYSCALL2(int, dup2, int, oldfd, int, newfd) +{ + if (newfd == oldfd) { + return newfd; + } + + int errno; + struct v_fd *oldfd_s, *newfd_s; + if (!GET_FD(oldfd, oldfd_s) || TEST_FD(newfd)) { + errno = EBADF; + goto done; + } + newfd_s = __current->fdtable->fds[newfd]; + if (newfd_s && (errno = vfs_close(newfd_s))) { + goto done; + } + + if (!(errno = __vfs_dup_fd(oldfd_s, &newfd_s))) { + __current->fdtable->fds[newfd] = newfd_s; + return newfd; + } + +done: + return DO_STATUS(errno); +} + +__DEFINE_LXSYSCALL1(int, dup, int, oldfd) +{ + int errno, newfd; + struct v_fd *oldfd_s, *newfd_s; + if (!GET_FD(oldfd, oldfd_s)) { + errno = EBADF; + } else if (!(errno = vfs_alloc_fdslot(&newfd)) && + !(errno = __vfs_dup_fd(oldfd_s, &newfd_s))) { + __current->fdtable->fds[newfd] = newfd_s; + return newfd; + } + return DO_STATUS(errno); } \ No newline at end of file diff --git a/lunaix-os/kernel/process.c b/lunaix-os/kernel/process.c index a9baaad..4d6a77e 100644 --- a/lunaix-os/kernel/process.c +++ b/lunaix-os/kernel/process.c @@ -184,6 +184,7 @@ dup_proc() pcb->intr_ctx = __current->intr_ctx; pcb->parent = __current; + memcpy(pcb->fdtable, __current->fdtable, sizeof(struct v_fdtable)); region_copy(&__current->mm.regions, &pcb->mm.regions); setup_proc_mem(pcb, PD_REFERENCED); diff --git a/lunaix-os/kernel/sched.c b/lunaix-os/kernel/sched.c index d1ee39d..37c02d1 100644 --- a/lunaix-os/kernel/sched.c +++ b/lunaix-os/kernel/sched.c @@ -319,6 +319,14 @@ destroy_process(pid_t pid) proc->state = PS_DESTROY; llist_delete(&proc->siblings); + for (size_t i = 0; i < VFS_MAX_FD; i++) { + struct v_fd* fd = proc->fdtable->fds[i]; + if (fd) + vfs_close(fd); + } + + vfree(proc->fdtable); + struct mm_region *pos, *n; llist_for_each(pos, n, &proc->mm.regions.head, head) { -- 2.27.0