feat: implement dup(2), dup2(2)
authorMinep <zelong56@gmail.com>
Sun, 31 Jul 2022 16:15:38 +0000 (17:15 +0100)
committerMinep <zelong56@gmail.com>
Sun, 31 Jul 2022 16:15:38 +0000 (17:15 +0100)
fix: free & copy the fd tables upon process destoryed or forked

README.md
lunaix-os/includes/lunaix/fs.h
lunaix-os/includes/lunaix/lunistd.h
lunaix-os/includes/lunaix/syscall.h
lunaix-os/kernel/asm/x86/syscall.S
lunaix-os/kernel/fs/vfs.c
lunaix-os/kernel/process.c
lunaix-os/kernel/sched.c

index de08a2ed0f214051112b851d069fc189deb7dba4..b9a96dc024805176f5484de09b17c5aa369d8149 100644 (file)
--- 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自有
 
index d233ff09e0289d05f84e2a3c9578254766b7b7bf..43a5cf4b68d1a3ab2153e37046ba1e02e0e89508 100644 (file)
@@ -101,6 +101,7 @@ struct v_fd
 {
     struct v_file* file;
     int pos;
+    int flags;
 };
 
 struct v_inode
index 9095c37dd2d2aefc5e063c83f29d7e6009a93a2f..472f638d8eac77c05417688b75f24c6fad173dae 100644 (file)
@@ -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 */
index 82986ab5f83783c73fe5acf75ba8c6ccbf1847dd..30941f6f23e2dbf007982fb20ae8add832f49945 100644 (file)
@@ -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
 #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
 
index be5660f1a8e7c78196bac1e0449f03fdb675b1bd..ae631176bd3f48b825b775c7813be82b0a45af33 100644 (file)
@@ -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
index de08cec798db3118efa96f230ed3bde4650dd578..05741d846f15df903cca7e9b524acce835eb5112 100644 (file)
@@ -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
index a9baaadd20aafac221136b9133662652190f3c21..4d6a77ee2f7a5f2ea5ba3ea7617d543c04a626e8 100644 (file)
@@ -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);
index d1ee39d21bc3424ce5399d2c60f71d53cea58dca..37c02d1c705988dc5d53b0e738bbaaa83370ce37 100644 (file)
@@ -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)
     {