diff --git a/basic/user/lib/syscall.c b/basic/user/lib/syscall.c index bafb1cc087923bdd44a1d9003f5ed1fdf39fc3cf..07a0f309f35d90ea3364332c8236a55c798e4de0 100644 --- a/basic/user/lib/syscall.c +++ b/basic/user/lib/syscall.c @@ -53,8 +53,8 @@ pid_t clone(int (*fn)(void *arg), void *arg, void *stack, size_t stack_size, uns if (stack) stack += stack_size; - return __clone(fn, stack, flags, NULL, NULL, NULL); - // return syscall(SYS_clone, fn, stack, flags, NULL, NULL, NULL); + // return __clone(fn, stack, flags, NULL, NULL, NULL); + return syscall(SYS_clone, fn, stack, flags, NULL, NULL, NULL); } void exit(int code) { diff --git a/include/defs.h b/include/defs.h index b8870254b0d990b63937adc621d27825df2fdd8f..cb101d6041d8b31854fe05a42c247bac7703ec4e 100644 --- a/include/defs.h +++ b/include/defs.h @@ -134,4 +134,12 @@ void virtio_disk_intr(void); // add -int wait4(int, int*, int); \ No newline at end of file +int wait4(int, int*, int); +int clone(unsigned long flags, void *stack, int *ptid, unsigned long tls, int *ctid); + +#define CLONE_VM 0x00000100 // 共享内å˜ç©ºé—´ +#define CLONE_FS 0x00000200 // å…±äº«æ–‡ä»¶ç³»ç»Ÿä¿¡æ¯ +#define CLONE_FILES 0x00000400 // 共享文件æè¿°ç¬¦è¡¨ +#define CLONE_PARENT 0x00000800 // 共享父进程 + +uint64 getppid(); \ No newline at end of file diff --git a/include/proc/proc.h b/include/proc/proc.h index 620147cbc66344c0db9d7f1848be6317a8eb3e79..9d3e00f707c44f80dc71a9df6cc2af2ce8bb1566 100644 --- a/include/proc/proc.h +++ b/include/proc/proc.h @@ -155,6 +155,7 @@ struct proc { //add struct vm_area vma[NVMA]; struct tms proc_tms; + }; #define WNOHANG 0x01 // Don't block waiting diff --git a/include/sys/syscall.h b/include/sys/syscall.h index 47a26f8ae10e8949625c00c633c1005119b20f4e..3087ac5255a761a30af41bd73a55639208aec014 100644 --- a/include/sys/syscall.h +++ b/include/sys/syscall.h @@ -29,8 +29,8 @@ #define SYS_close 57 #define SYS_mknod 16 -#define SYS_clone 220 +#define SYS_clone 220 #define SYS_umount2 39 #define SYS_mount 40 #define SYS_brk 214 @@ -43,4 +43,4 @@ #define SYS_nanosleep 101 #define SYS_getcwd 17 #define SYS_getdents64 61 -#define SYS_shutdown 19 \ No newline at end of file +#define SYS_shutdown 19 diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index 2c4c3b00bb20644fed8083844b804cf7aaad38e7..d9689991846573aa38962dcd457b337d6c96f3c3 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -361,7 +361,7 @@ fork(void) // copy saved user registers. *(np->trapframe) = *(p->trapframe); - + np->parent = p; // 设置父进程 // Cause fork to return 0 in the child. np->trapframe->a0 = 0; @@ -820,3 +820,121 @@ wait4(int pid, int *status, int options) } } + +int +clone(unsigned long flags, void *stack, int *ptid, unsigned long tls, int *ctid) +{ + int i, pid; + struct proc *np; + struct proc *p = myproc(); + + // Allocate process. + if((np = allocproc()) == 0){ + return -1; + } + + // Copy user memory from parent to child. + if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){ + freeproc(np); + release(&np->lock); + return -1; + } + np->sz = p->sz; + + // Copy saved user registers. + *(np->trapframe) = *(p->trapframe); + np->parent = p; // 设置父进程 + // Cause clone to return 0 in the child. + np->trapframe->a0 = 0; + + // Set new stack pointer if specified + if(stack != 0) { + np->trapframe->sp = (uint64)stack; + } + + // Handle file descriptors based on flags + if(!(flags & CLONE_FILES)) { + // Default behavior - duplicate file descriptors + for(i = 0; i < NOFILE; i++) { + if(p->ofile[i]) { + np->ofile[i] = get_fops()->dup(p->ofile[i]); + } + } + } else { + // Share file descriptor table - just copy pointers + for(i = 0; i < NOFILE; i++) { + np->ofile[i] = p->ofile[i]; + if(p->ofile[i]) { + // Increment reference count using dup instead of hold + get_fops()->dup(p->ofile[i]); + } + } + } + + for(i = 0; i < NVMA; ++i) { + if(p->vma[i].used) { + if(!(flags & CLONE_VM)) { + memmove(&np->vma[i], &p->vma[i], sizeof(p->vma[i])); + get_fops()->dup(p->vma[i].vfile); + } else { + np->vma[i] = p->vma[i]; + get_fops()->dup(p->vma[i].vfile); + } + } + } + + if(!(flags & CLONE_FS)) { + np->cwd.fs = p->cwd.fs; + strcpy(np->cwd.path, p->cwd.path); + } else { + np->cwd = p->cwd; + } + + strcpy(np->name, p->name); + + if(ptid != 0) { + if(copyout(np->pagetable, (uint64)ptid, (char *)&p->pid, sizeof(p->pid)) < 0) { + freeproc(np); + release(&np->lock); + return -1; + } + } + + if(ctid != 0) { + if(copyout(np->pagetable, (uint64)ctid, (char *)&np->pid, sizeof(np->pid)) < 0) { + freeproc(np); + release(&np->lock); + return -1; + } + } + + pid = np->pid; + + release(&np->lock); + + acquire(&wait_lock); + if(flags & CLONE_PARENT) { + np->parent = p->parent; + } else { + np->parent = p; + } + release(&wait_lock); + + acquire(&np->lock); + np->state = RUNNABLE; + release(&np->lock); + + return pid; +} + +uint64 +getppid(void) +{ + struct proc *curproc = myproc(); + + if(curproc->parent == 0) { + return 1; + } + + return curproc->parent->pid; +} \ No newline at end of file diff --git a/kernel/sys/syscall.c b/kernel/sys/syscall.c index 0719177443354784457217013d8eab3e868d6a2c..7b810de297f037a18225d7a116003af18e5f4ec8 100644 --- a/kernel/sys/syscall.c +++ b/kernel/sys/syscall.c @@ -100,7 +100,7 @@ extern uint64 sys_linkat(void); extern uint64 sys_mkdirat(void); extern uint64 sys_close(void); //add - +extern uint64 sys_clone(void); extern uint64 sys_mknod(void); extern uint64 sys_exec(void); extern uint64 sys_pipe2(void); @@ -119,6 +119,7 @@ extern uint64 sys_sched_yield(void); extern uint64 sys_uname(void); extern uint64 sys_nanosleep(void); extern uint64 sys_shutdown(void); +extern uint64 sys_getppid(void); // An array mapping syscall numbers from syscall.h // to the function that handles the system call. @@ -144,7 +145,7 @@ static uint64 (*syscalls[])(void) = { [SYS_mkdirat] sys_mkdirat, [SYS_close] sys_close, //add - +[SYS_clone] sys_clone, [SYS_mknod] sys_mknod, [SYS_exec] sys_exec, [SYS_getcwd] sys_getcwd, @@ -161,6 +162,7 @@ static uint64 (*syscalls[])(void) = { [SYS_uname] sys_uname, [SYS_nanosleep] sys_nanosleep, [SYS_shutdown] sys_shutdown, +[SYS_getppid] sys_getppid, }; void diff --git a/kernel/sys/sysproc.c b/kernel/sys/sysproc.c index db29a882fad71958e450844b9c54c03b30665884..722386482b2d3f3a1fd2569fb7d8abacbaba28d1 100644 --- a/kernel/sys/sysproc.c +++ b/kernel/sys/sysproc.c @@ -94,8 +94,28 @@ sys_wait4(void) return wait4(pid, (int*)status, options); } +int +sys_clone(void) +{ + int flags; + uint64 stack, tls, ctid, ptid; + argint(0, &flags); + argaddr(1, &stack); + argaddr(2, &ptid); + argaddr(3, &tls); + argaddr(4, &ctid); + return clone(flags, (void*)stack, (int*)(uint64)ptid, tls, (int*)(uint64)ctid); +} + + uint64 sys_shutdown(void) { struct filesystem *fs = get_fs_from_path("/"); vfs_ext_umount(fs); sbi_shutdown(); +} + +uint64 +sys_getppid(void) +{ + return getppid(); } \ No newline at end of file diff --git a/user/deps/usys.S b/user/deps/usys.S index 7714c0f7dac13940361827fd21585c5dff720810..7a0a439ad39d096160c47aff67ba3df777dc54d6 100644 --- a/user/deps/usys.S +++ b/user/deps/usys.S @@ -160,3 +160,13 @@ shutdown: li a7, SYS_shutdown ecall ret +.global clone +clone: + li a7, SYS_clone + ecall + ret +.global getppid +getppid: + li a7, SYS_getppid + ecall + ret diff --git a/user/deps/usys.pl b/user/deps/usys.pl index 76ec8897e1fd7d158226650d1fbafa8190759224..60f9b6db38b1f3d76851d09561b8fabfdee231b9 100644 --- a/user/deps/usys.pl +++ b/user/deps/usys.pl @@ -50,6 +50,9 @@ entry("munmap"); entry("times"); + # proc entry("wait4"); entry("shutdown"); +entry("clone"); +entry("getppid"); diff --git a/user/user.h b/user/user.h index 030d12852c6c6ca35c97d8838510d81e35736e0f..f26596308b9bce4ae6b971209ee73935bd81123d 100644 --- a/user/user.h +++ b/user/user.h @@ -72,7 +72,7 @@ int getdents64(int, struct dirent*, int); int umount2(const char*, int); int mount(const char*, const char*, const char*, uint64, const void *); int wait4(int, int *, int); - +int clone(int(*)(void*), void*, void*, int, int); #define O_RDONLY 0x000 #define O_WRONLY 0x001 @@ -85,5 +85,5 @@ int wait4(int, int *, int); #define AT_FDCWD -100 #define DIRSIZ 260 - +int getppid(void);