/* Initialize all services and execute user level code */ void init_systems(void) { if (!fork()) { do { sys_exec("user/services/pipe_master"); printa("pipe_master error\n"); } while (1); } if (!fork()) sys_exec("user/user_first"); while (1); }
/* Execute a command line. */ int _stdcall execute_line (char *line) { register int i; COMMAND *command; char *word ; /* Isolate the command word. */ i = 0; while (line[i] && whitespace (line[i])) i++; word = line + i; while (line[i] && !whitespace (line[i])) i++; if (line[i]) line[i++] = '\0'; command = find_command(word); /* Get argument to command, if any. */ while (whitespace (line[i])) i++; word = line + i; sprintf(line_ex, "%s %s \n\0", line, word); /* printf( ":: %s %s \n\0", line, word); */ if ((!command)|| (find_command(line)->func == find_command("plot")->func )) { return (iff_exec (line_ex)); } else if (find_command(line)->func == find_command("dir")->func) { return (sys_exec(line_ex)); } else { return ((*(command->func)) (word)); } }
int main(int argc, char** argv) { init(); FILE* f; f=fopen("ref.txt","w"); solve1(); print(f); fclose(f); f=fopen("t.txt","w"); solve2(); print(f); fclose(f); int r=sys_exec("diff","-dur","ref.txt","t.txt",NULL); printf("\n\n"); sys_exec("cat","t.txt",NULL); printf("\nCorrectness: %s\n",!r?"no differences":"FAILURE !!!"); unlink("ref.txt"); unlink("t.txt"); cleanup(); return 0; }
int __exec(const char *name, const char **argv) { int argc = 0; while (argv[argc] != NULL) { argc ++; } return sys_exec(name, argc, argv); }
int __exec(const char *name, const char **argv, const char **envp) { int argc = 0; while (argv[argc] != NULL) { argc++; } return sys_exec(argv[0], argv, envp); }
void exec_bootproc(struct vmproc *vmp, struct boot_image *ip) { struct vm_exec_info vmexeci; struct exec_info *execi = &vmexeci.execi; char hdr[VM_PAGE_SIZE]; memset(&vmexeci, 0, sizeof(vmexeci)); if(pt_new(&vmp->vm_pt) != OK) panic("VM: no new pagetable"); if(pt_bind(&vmp->vm_pt, vmp) != OK) panic("VM: pt_bind failed"); if(sys_physcopy(NONE, ip->start_addr, SELF, (vir_bytes) hdr, sizeof(hdr)) != OK) panic("can't look at boot proc header"); execi->stack_high = kernel_boot_info.user_sp; execi->stack_size = DEFAULT_STACK_LIMIT; execi->proc_e = vmp->vm_endpoint; execi->hdr = hdr; execi->hdr_len = sizeof(hdr); strlcpy(execi->progname, ip->proc_name, sizeof(execi->progname)); execi->frame_len = 0; execi->opaque = &vmexeci; execi->filesize = ip->len; vmexeci.ip = ip; vmexeci.vmp = vmp; /* callback functions and data */ execi->copymem = libexec_copy_physcopy; execi->clearproc = NULL; execi->clearmem = libexec_clear_sys_memset; execi->allocmem_prealloc_junk = libexec_alloc_vm_prealloc; execi->allocmem_prealloc_cleared = libexec_alloc_vm_prealloc; execi->allocmem_ondemand = libexec_alloc_vm_ondemand; if(libexec_load_elf(execi) != OK) panic("vm: boot process load of process %s (ep=%d) failed\n", execi->progname,vmp->vm_endpoint); if(sys_exec(vmp->vm_endpoint, (char *) execi->stack_high - 12, (char *) ip->proc_name, execi->pc) != OK) panic("vm: boot process exec of process %s (ep=%d) failed\n", execi->progname,vmp->vm_endpoint); /* make it runnable */ if(sys_vmctl(vmp->vm_endpoint, VMCTL_BOOTINHIBIT_CLEAR, 0) != OK) panic("VMCTL_BOOTINHIBIT_CLEAR failed"); }
static void *exec_thread(void *arg) { Exec *e = arg; for (;;) { int p = 0, pid = -1; /* creating processor */ IO *sio = sys_socket(&p); char port[8]; str_print(port, "%d", p); char *argv[] = {e->exe, "processor", "-p", port, "-t", e->tx, NULL}; pid = sys_exec(argv); if (!sys_iready(sio, PROC_WAIT_SEC)) { sys_log('E', "failed to fork a processor\n"); } else { IO *pio = sys_accept(sio, IO_CHUNK); int ok = 1; while (ok) { pio->stop = 0; Conn *c = queue_get(e->runq); int pcnt = 0, ccnt = 0; sys_proxy(c->io, &ccnt, pio, &pcnt); ok = pio->stop == IO_TERM || (ccnt == 0 && !pio->stop); if (!ok && pcnt == 0) { int status = http_500(c->io); sys_log('E', "failed with status %d\n", status); } c->time = sys_millis(); queue_put(e->waitq, c); } sys_close(pio); } sys_close(sio); if (pid != -1) { sys_kill(pid); sys_wait(pid); } } mem_free(e); return NULL; }
/*===========================================================================* * exec_restart * *===========================================================================*/ void exec_restart(struct mproc *rmp, int result, vir_bytes pc, vir_bytes sp, vir_bytes ps_str) { int r, sn; if (result != OK) { if (rmp->mp_flags & PARTIAL_EXEC) { /* Use SIGKILL to signal that something went wrong */ sys_kill(rmp->mp_endpoint, SIGKILL); return; } reply(rmp-mproc, result); return; } rmp->mp_flags &= ~PARTIAL_EXEC; /* Fix 'mproc' fields, tell kernel that exec is done, reset caught * sigs. */ for (sn = 1; sn < _NSIG; sn++) { if (sigismember(&rmp->mp_catch, sn)) { sigdelset(&rmp->mp_catch, sn); rmp->mp_sigact[sn].sa_handler = SIG_DFL; sigemptyset(&rmp->mp_sigact[sn].sa_mask); } } /* Cause a signal if this process is traced. * Do this before making the process runnable again! */ if (rmp->mp_tracer != NO_TRACER && !(rmp->mp_trace_flags & TO_NOEXEC)) { sn = (rmp->mp_trace_flags & TO_ALTEXEC) ? SIGSTOP : SIGTRAP; check_sig(rmp->mp_pid, sn, FALSE /* ksig */); } /* Call kernel to exec with SP and PC set by VFS. */ r = sys_exec(rmp->mp_endpoint, sp, (vir_bytes)rmp->mp_name, pc, ps_str); if (r != OK) panic("sys_exec failed: %d", r); }
int main(int argc, char *argv[]) { vir_machine_init(); bootstrap(); os_init(); char order[800]; int i; while (1) { echo_mip4(); mips_want_get_string(order, 799); switch(order[0]) { case 'e': sys_exec(order + 2); break; case 'f': format_disk(); write_stdout("successfully formats the disk!\n", F_WHITE, B_BLACK); break; case 'c': sys_create(order + 2); write_stdout("successfully create file\n", F_WHITE, B_BLACK); break; case 'w': // copy the file to disk! { char *name = order + 2; // only one spaces ! sys_create(name); int fid = sys_open(name); int obj_id = open(name, O_RDONLY); while (1) { int buf; if (read(obj_id, &buf, 1) == 0) break; char char_buf = (char)buf; sys_write(fid, &char_buf, 1); } sys_close(fid); write_stdout("successfully write file\n", F_WHITE, B_BLACK); break; } } } return 0; }
static void syscall_handler (struct intr_frame *f) { if(f) { stack_address_check(f->esp); // get sys call number off the stack int sys_call_no = get_nth_arg_int(f->esp, 0); DPRINTF("system call! %d\n", sys_call_no); switch(sys_call_no) { case SYS_HALT: power_off(); break; case SYS_EXIT: { int status = get_nth_arg_int(f->esp, 1); thread_current()->exit_status = status; process_terminate(); return; } break; case SYS_EXEC: { char* file_name = (char*)get_nth_arg_ptr(f->esp, 1); user_string_add_range_check_and_terminate(file_name); int tid = sys_exec(file_name); DPRINTF("exec %s, tid = %d\n", file_name, tid); f->eax = tid; } return; case SYS_WAIT: { int pid = get_nth_arg_int(f->esp, 1); int ret = process_wait(pid); DPRINTF("wait for pid %d by %d return %d\n", pid, thread_current()->tid ,ret); f->eax = ret; } return; case SYS_CREATE: { char* file_name = (char*)get_nth_arg_ptr(f->esp, 1); user_string_add_range_check_and_terminate(file_name); int size = get_nth_arg_int(f->esp, 2); DPRINTF("sys_create(%s,%d)\n", file_name, size); f->eax = sys_create(file_name, size); } return; case SYS_REMOVE: { char* file_name = (char*)get_nth_arg_ptr(f->esp, 1); user_string_add_range_check_and_terminate(file_name); DPRINTF("sys_remove(%s)\n", file_name); f->eax = sys_remove(file_name); } return; case SYS_OPEN: { char* file_name = (char*)get_nth_arg_ptr(f->esp, 1); user_string_add_range_check_and_terminate(file_name); DPRINTF("sys_open(%s)\n", file_name); f->eax = sys_open(file_name); } return; case SYS_FILESIZE: { int fd = get_nth_arg_int(f->esp, 1); DPRINTF("sys_filesize(%d)\n", fd); f->eax = sys_filesize(fd); } return; case SYS_READ: { int fd = get_nth_arg_int(f->esp, 1); char* buf = (char*)get_nth_arg_ptr(f->esp, 2); int size = get_nth_arg_int(f->esp, 3); user_add_range_check_and_terminate(buf, size); DPRINTF("sys_read(%d,%s,%d)\n", fd, buf, size); f->eax = sys_read(fd, buf, size); } return; case SYS_WRITE: { int fd = get_nth_arg_int(f->esp, 1); char* buf = (char*)get_nth_arg_ptr(f->esp, 2); int size = get_nth_arg_int(f->esp, 3); user_add_range_check_and_terminate(buf, size); DPRINTF("sys_write(%d,%s,%d)\n", fd, buf, size); f->eax = sys_write(fd, buf, size); } return; case SYS_SEEK: { int fd = get_nth_arg_int(f->esp, 1); unsigned pos = get_nth_arg_int(f->esp, 2); DPRINTF("sys_seek(%d,%d)\n", fd, pos); sys_seek(fd, pos); } return; case SYS_TELL: { int fd = get_nth_arg_int(f->esp, 1); DPRINTF("sys_tell(%d)\n", fd); f->eax = sys_tell(fd); } return; case SYS_CLOSE: { int fd = get_nth_arg_int(f->esp, 1); DPRINTF("sys_close(%d)\n", fd); sys_close(fd); } return; /* case SYS_MMAP: case SYS_MUNMAP: case SYS_CHDIR: case SYS_MKDIR: case SYS_READDIR: case SYS_ISDIR: case SYS_INUMBER: */ default: thread_exit(); break; } } else thread_exit(); }
/*===========================================================================* * do_exec * *===========================================================================*/ PUBLIC int do_exec() { /* Perform the execve(name, argv, envp) call. The user library builds a * complete stack image, including pointers, args, environ, etc. The stack * is copied to a buffer inside PM, and then to the new core image. */ /* * 执行 execve(name, argv, envp) 调用. 用户库函数构造了一个完整的栈映像, * 包括指针, 命令行参数, 环境变量等等. 栈先复制到 PM 内的一个缓冲区中, * 再复制给新的堆栈映像. */ register struct mproc *rmp; struct mproc *sh_mp; int m, r, fd, ft, sn; static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ static char name_buf[PATH_MAX]; /* the name of the file to exec */ char *new_sp, *name, *basename; vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp; phys_bytes tot_bytes; /* total space for program, including gap */ long sym_bytes; vir_clicks sc; struct stat s_buf[2], *s_p; vir_bytes pc; /* Do some validity checks. */ rmp = mp; // rmp = mp = 当前进程的 struct mproc 结构 stk_bytes = (vir_bytes) m_in.stack_bytes; if (stk_bytes > ARG_MAX) return(ENOMEM); /* stack too big */ if (m_in.exec_len <= 0 || m_in.exec_len > PATH_MAX) return(EINVAL); /* Get the exec file name and see if the file is executable. */ src = (vir_bytes) m_in.exec_name; dst = (vir_bytes) name_buf; // 将可执行文件的路径名从主调进程复制到 PM 的 name_buf[] 中. r = sys_datacopy(who, (vir_bytes) src, PM_PROC_NR, (vir_bytes) dst, (phys_bytes) m_in.exec_len); if (r != OK) return(r); /* file name not in user data segment */ /* Fetch the stack from the user before destroying the old core image. */ // 将主调进程的栈复制到 mbuf[], 在毁掉旧的核心映像之前 src = (vir_bytes) m_in.stack_ptr; dst = (vir_bytes) mbuf; r = sys_datacopy(who, (vir_bytes) src, PM_PROC_NR, (vir_bytes) dst, (phys_bytes)stk_bytes); /* can't fetch stack (e.g. bad virtual addr) */ if (r != OK) return(EACCES); r = 0; /* r = 0 (first attempt), or 1 (interpreted script) */ name = name_buf; /* name of file to exec. */ do { s_p = &s_buf[r]; // 切换到主调进程的当前工作目录 tell_fs(CHDIR, who, FALSE, 0); /* switch to the user's FS environ */ // 检查文件是否可执行, 如果可执行, 返回文件描述符 fd = allowed(name, s_p, X_BIT); /* is file executable? */ if (fd < 0) return(fd); /* file was not executable */ /* Read the file header and extract the segment sizes. */ sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; // 读取文件头部数据, 并赋值给相应参数 m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, &tot_bytes, &sym_bytes, sc, &pc); if (m != ESCRIPT || ++r > 1) break; } while ((name = patch_stack(fd, mbuf, &stk_bytes, name_buf)) != NULL); if (m < 0) { close(fd); /* something wrong with header */ return(stk_bytes > ARG_MAX ? ENOMEM : ENOEXEC); } /* Can the process' text be shared with that of one already running? */ sh_mp = find_share(rmp, s_p->st_ino, s_p->st_dev, s_p->st_ctime); /* Allocate new memory and release old memory. Fix map and tell kernel. */ r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes); if (r != OK) { close(fd); /* insufficient core or program too big */ return(r); } /* Save file identification to allow it to be shared. */ rmp->mp_ino = s_p->st_ino; rmp->mp_dev = s_p->st_dev; rmp->mp_ctime = s_p->st_ctime; /* Patch up stack and copy it from PM to new core image. */ vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT; vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT; vsp -= stk_bytes; patch_ptr(mbuf, vsp); src = (vir_bytes) mbuf; r = sys_datacopy(PM_PROC_NR, (vir_bytes) src, who, (vir_bytes) vsp, (phys_bytes)stk_bytes); if (r != OK) panic(__FILE__,"do_exec stack copy err on", who); /* Read in text and data segments. */ if (sh_mp != NULL) { lseek(fd, (off_t) text_bytes, SEEK_CUR); /* shared: skip text */ } else { rw_seg(0, fd, who, T, text_bytes); } rw_seg(0, fd, who, D, data_bytes); close(fd); /* don't need exec file any more */ /* Take care of setuid/setgid bits. */ if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */ if (s_buf[0].st_mode & I_SET_UID_BIT) { rmp->mp_effuid = s_buf[0].st_uid; tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid); } if (s_buf[0].st_mode & I_SET_GID_BIT) { rmp->mp_effgid = s_buf[0].st_gid; tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid); } } /* Save offset to initial argc (for ps) */ rmp->mp_procargs = vsp; /* Fix 'mproc' fields, tell kernel that exec is done, reset caught sigs. */ for (sn = 1; sn <= _NSIG; sn++) { if (sigismember(&rmp->mp_catch, sn)) { sigdelset(&rmp->mp_catch, sn); rmp->mp_sigact[sn].sa_handler = SIG_DFL; sigemptyset(&rmp->mp_sigact[sn].sa_mask); } } rmp->mp_flags &= ~SEPARATE; /* turn off SEPARATE bit */ rmp->mp_flags |= ft; /* turn it on for separate I & D files */ new_sp = (char *) vsp; tell_fs(EXEC, who, 0, 0); /* allow FS to handle FD_CLOEXEC files */ /* System will save command line for debugging, ps(1) output, etc. */ basename = strrchr(name, '/'); if (basename == NULL) basename = name; else basename++; strncpy(rmp->mp_name, basename, PROC_NAME_LEN-1); rmp->mp_name[PROC_NAME_LEN] = '\0'; sys_exec(who, new_sp, basename, pc); /* Cause a signal if this process is traced. */ if (rmp->mp_flags & TRACED) check_sig(rmp->mp_pid, SIGTRAP); return(SUSPEND); /* no reply, new program just runs */ }
int do_syscalls(int syscall_id,const struct cpu_state *user_ctxt) { int ret ; switch(syscall_id) { case SYSCALL_ID_EXEC:{ __u32 user_str, len , argc ; __u32 len_args; char **src_argaddr; char **ap; char **param; char * str; int i; /* Get the user arguments */ ret = syscall_get4args(user_ctxt, & user_str, & len, & src_argaddr, & len_args); if (ret != 0 ) break; ap = src_argaddr; argc = 0; while (*ap++) argc++; if (argc) { param = (char**) kmalloc(sizeof(char*) * (argc+1),0); for (i=0 ; i<argc ; i++) { param[i] = (char*) kmalloc(strlen(src_argaddr[i]) + 1, 0); strcpy(param[i], src_argaddr[i]); } param[i] = 0; } str =(char*) kmalloc(len +1, 0); if (! str) { ret = -3; break; } ret = strzcpy_from_user(str,user_str,len + 1); if (0 > ret) { kfree((__u32)str); break; } sys_exec(str, param ); struct process *proc = current ; asm("mov %0, %%eax; mov %%eax, %%cr3"::"m"(proc->regs.cr3)); } break; case 2:{ __u32 u_str, len ; char * str; ret = syscall_get2args(user_ctxt, & u_str, & len); if (ret != 0 ) break; str =(char*) kmalloc(len +1, 0); if (! str) { ret = -3; break; } ret = strzcpy_from_user(str,u_str,len + 1); if (0 > ret) { kfree((__u32)str); break; } kprintf("%s",(char*)str); kfree((__u32)str); } break; case 3:{ sys_exit(); } break; case SYSCALL_ID_MOUNT :{ __u32 user_src; size_t srclen; char * kernel_src = NULL; __u32 user_target; size_t target_len; char * kernel_target; __u32 mountflags; __u32 user_fstype; char * kernel_fstype; __u32 user_args; char * kernel_args = NULL; ret = syscall_get7args( user_ctxt ,&user_src ,&srclen, &user_target , &target_len , &user_fstype, &mountflags,&user_args); if (user_src != (__u32)NULL) { kernel_src =(char*) kmalloc(srclen +1 , 0); ret = strzcpy_from_user(kernel_src,user_src,srclen + 1); } kernel_target =(char*) kmalloc(target_len + 1 , 0); ret = strzcpy_from_user(kernel_target,user_target,target_len + 1); if ( OK != ret) { if (kernel_src) kfree((__u32)kernel_src); break; } kernel_fstype =(char*) kmalloc(256 , 0); ret = strzcpy_from_user(kernel_fstype,user_fstype,256); if (OK != ret) { if (kernel_src) kfree((__u32)kernel_src); kfree((__u32)kernel_target); break; } if (user_args != (__u32)NULL) { kernel_args =(char*) kmalloc(1024 , 0); ret = strzcpy_from_user(kernel_args,user_args,1024); if (OK != ret) { if (kernel_src) kfree((__u32)kernel_src); kfree((__u32)kernel_target); kfree((__u32)kernel_fstype); break; } } vfs_mount(kernel_src, kernel_target, kernel_fstype ); } break; case SYSCALL_ID_OPEN :{ __u32 user_str; __u32 len; __u32 open_flags; char * path; ret = syscall_get3args(user_ctxt, &user_str, &len,&open_flags); path =(char*) kmalloc(len +1 , 0); ret = strzcpy_from_user(path,user_str,len + 1); if (OK != ret) break; ret = sys_open( path , open_flags); kfree((__u32)path); } break; case SYSCALL_ID_WRITE :{ __u32 uaddr_buf; __u32 buflen; int fd; ret = syscall_get3args(user_ctxt, &fd,&uaddr_buf,&buflen); if (OK != ret) break; ret=sys_write(fd,(void*)uaddr_buf,buflen); } break; case SYSCALL_ID_READ:{ __u32 uaddr_buf; __u32 buflen; int fd; ret = syscall_get3args(user_ctxt, &fd,&uaddr_buf,&buflen); if (OK != ret) break; ret=sys_read(fd,(void*)uaddr_buf,buflen); } break; case SYSCALL_ID_BRK: { __u32 new_top_heap; struct uvmm_as * as; struct process *process = current ; as = process_get_address_space(process); if (! as) { debug(); return -7; } ret = syscall_get1arg(user_ctxt,&new_top_heap); if (OK != ret) break; ret = uvmm_brk(as, new_top_heap); } break; default: kprintf("unknown syscall %d\n", syscall_id); break; } return 0 ; }
/* Syscall handler calls the appropriate function. */ static void syscall_handler (struct intr_frame *f) { int ret = 0; int *syscall_nr = (int *) f->esp; void *arg1 = (int *) f->esp + 1; void *arg2 = (int *) f->esp + 2; void *arg3 = (int *) f->esp + 3; /* Check validate pointer. */ if (!is_user_vaddr (syscall_nr) || !is_user_vaddr (arg1) || !is_user_vaddr (arg2) || !is_user_vaddr (arg3)) sys_exit (-1); switch (*syscall_nr) { case SYS_HALT: sys_halt (); break; case SYS_EXIT: sys_exit (*(int *) arg1); break; case SYS_EXEC: ret = sys_exec (*(char **) arg1); break; case SYS_WAIT: ret = sys_wait (*(pid_t *) arg1); break; case SYS_CREATE: ret = sys_create (*(char **) arg1, *(unsigned *) arg2); break; case SYS_REMOVE: ret = sys_remove (*(char **) arg1); break; case SYS_OPEN: ret = sys_open (*(char **) arg1); break; case SYS_FILESIZE: ret = sys_filesize (*(int *) arg1); break; case SYS_READ: ret = sys_read (*(int *) arg1, *(void **) arg2, *(unsigned *) arg3); break; case SYS_WRITE: ret = sys_write (*(int *) arg1, *(void **) arg2, *(unsigned *) arg3); break; case SYS_SEEK: sys_seek (*(int *) arg1, *(unsigned *) arg2); break; case SYS_TELL: ret = sys_tell (*(int *) arg1); break; case SYS_CLOSE: sys_close (*(int *) arg1); break; default: printf (" (%s) system call! (%d)\n", thread_name (), *syscall_nr); sys_exit (-1); break; } f->eax = ret; }
static void syscall_handler (struct intr_frame *f) { /* Check to see that we can read supplied user memory pointer, using the check_mem_ptr helper() function, in get_word_from_stack(). If the check fails, the process is terminated. */ int syscall_number = (int)get_word_on_stack(f, 0); switch(syscall_number) { case SYS_HALT: { sys_halt(); break; } case SYS_EXIT: { int status = (int)get_word_on_stack(f, 1); sys_exit(status); /* Returns exit status to the kernel. */ f->eax = status; break; } case SYS_EXEC: { const char *cmd_line = (const char *)get_word_on_stack(f, 1); pid_t pid = sys_exec(cmd_line); /* Returns new processes pid. */ f->eax = pid; break; } case SYS_WAIT: { pid_t pid = (pid_t)get_word_on_stack(f, 1); /* Returns child's exit status (pid argument is pid of this child). */ f->eax = sys_wait(pid); break; } case SYS_CREATE: { const char *filename = (const char *)get_word_on_stack(f, 1); unsigned initial_size = (unsigned)get_word_on_stack(f, 2); /* Returns true to the kernel if creation is successful. */ f->eax = (int)sys_create(filename, initial_size); break; } case SYS_REMOVE: { const char *filename = (const char *)get_word_on_stack(f, 1); /* Returns true if successful, and false otherwise. */ f->eax = sys_remove(filename); break; } case SYS_OPEN: { const char *filename = (const char *)get_word_on_stack(f, 1); /* Returns file descriptor of opened file, or -1 if it could not be opened. */ f->eax = sys_open(filename); break; } case SYS_FILESIZE: { int fd = (int)get_word_on_stack(f, 1); /* Returns size of file in bytes. */ f->eax = sys_filesize(fd); break; } case SYS_READ: { int fd = (int)get_word_on_stack(f, 1); void *buffer = (void *)get_word_on_stack(f, 2); unsigned size = (unsigned)get_word_on_stack(f, 3); /* Returns number of bytes actually read, or -1 if it could not be read. */ f->eax = sys_read(fd, buffer, size, f); break; } case SYS_WRITE: { int fd = (int)get_word_on_stack(f, 1); void *buffer = (void *)get_word_on_stack(f, 2); unsigned size = (unsigned)get_word_on_stack(f, 3); /* Returns number of bytes written. */ f->eax = sys_write(fd, buffer, size); break; } case SYS_SEEK: { int fd = (int)get_word_on_stack(f, 1); unsigned position = (int)get_word_on_stack(f, 2); sys_seek(fd, position); break; } case SYS_TELL: { int fd = (int)get_word_on_stack(f, 1); /* Returns the position of the next byte to be read or written in open file 'fd' (in bytes, from start of file). */ f->eax = sys_tell(fd); break; } case SYS_CLOSE: { int fd = (int)get_word_on_stack(f, 1); sys_close(fd); break; } case SYS_MMAP: { int fd = (int)get_word_on_stack(f, 1); void *addr = (void *)get_word_on_stack(f, 2); f->eax = sys_mmap(fd, addr); break; } case SYS_MUNMAP: { mapid_t mapping = (mapid_t)get_word_on_stack(f, 1); sys_munmap(mapping); break; } default: { NOT_REACHED(); } } }
void trap_kernel_handler(struct user_context *user_ctx) { _debug("...... in %s, code = %p\n", __func__, user_ctx->code & ~YALNIX_PREFIX); switch (user_ctx->code) { case YALNIX_FORK: SET_RET(user_ctx, sys_fork(user_ctx)); break; case YALNIX_EXEC: sys_exec((char *)user_ctx->regs[0], (char **)user_ctx->regs[1], user_ctx); break; case YALNIX_EXIT: sys_exit(user_ctx->regs[0], user_ctx); break; case YALNIX_WAIT: if (!FROM_USER_SPACE(user_ctx->regs[0])) { _error("Bad man! Please pass user space pointer!\n"); sys_exit(ERROR, user_ctx); } SET_RET(user_ctx, sys_wait((int *)user_ctx->regs[0], user_ctx)); break; case YALNIX_GETPID: SET_RET(user_ctx, sys_getpid()); break; case YALNIX_BRK: SET_RET(user_ctx, sys_brk(user_ctx->regs[0])); break; case YALNIX_DELAY: SET_RET(user_ctx, sys_delay(user_ctx->regs[0], user_ctx)); break; case YALNIX_TTY_READ: if (!FROM_USER_SPACE(user_ctx->regs[1])) { _error("Bad man! Please pass user space pointer!\n"); sys_exit(ERROR, user_ctx); } SET_RET(user_ctx, sys_tty_read(user_ctx->regs[0], (char *)user_ctx->regs[1], user_ctx->regs[2], user_ctx)); break; case YALNIX_TTY_WRITE: if (!FROM_USER_SPACE(user_ctx->regs[1])) { _error("Bad man! Please pass user space pointer!\n"); sys_exit(ERROR, user_ctx); } SET_RET(user_ctx, sys_tty_write(user_ctx->regs[0], (char *)user_ctx->regs[1], user_ctx->regs[2], user_ctx)); break; case YALNIX_PIPE_INIT: if (!FROM_USER_SPACE(user_ctx->regs[0])) { _error("Bad man! Please pass user space pointer!\n"); sys_exit(ERROR, user_ctx); } SET_RET(user_ctx, sys_pipe_init((unsigned int *) user_ctx->regs[0])); break; case YALNIX_PIPE_READ: if (!FROM_USER_SPACE(user_ctx->regs[1])) { _error("Bad man! Please pass user space pointer!\n"); sys_exit(ERROR, user_ctx); } SET_RET(user_ctx, sys_pipe_read(user_ctx->regs[0], (char *)user_ctx->regs[1], user_ctx->regs[2], user_ctx)); break; case YALNIX_PIPE_WRITE: if (!FROM_USER_SPACE(user_ctx->regs[1])) { _error("Bad man! Please pass user space pointer!\n"); sys_exit(ERROR, user_ctx); } SET_RET(user_ctx, sys_pipe_write(user_ctx->regs[0], (char *)user_ctx->regs[1], user_ctx->regs[2], user_ctx)); break; case YALNIX_LOCK_INIT: if (!FROM_USER_SPACE(user_ctx->regs[0])) { _error("Bad man! Please pass user space pointer!\n"); sys_exit(ERROR, user_ctx); } SET_RET(user_ctx, sys_lock_init((unsigned int *) user_ctx->regs[0])); break; case YALNIX_LOCK_ACQUIRE: SET_RET(user_ctx, sys_lock_acquire(user_ctx->regs[0], user_ctx)); break; case YALNIX_LOCK_RELEASE: SET_RET(user_ctx, sys_lock_release(user_ctx->regs[0])); break; case YALNIX_CVAR_INIT: if (!FROM_USER_SPACE(user_ctx->regs[0])) { _error("Bad man! Please pass user space pointer!\n"); sys_exit(ERROR, user_ctx); } SET_RET(user_ctx, sys_cvar_init((unsigned int *) user_ctx->regs[0])); break; case YALNIX_CVAR_WAIT: SET_RET(user_ctx, sys_cvar_wait(user_ctx->regs[0], user_ctx->regs[1], user_ctx)); break; case YALNIX_CVAR_SIGNAL: SET_RET(user_ctx, sys_cvar_signal(user_ctx->regs[0])); break; case YALNIX_CVAR_BROADCAST: SET_RET(user_ctx, sys_cvar_broadcast(user_ctx->regs[0])); break; case YALNIX_RECLAIM: SET_RET(user_ctx, sys_reclaim(user_ctx->regs[0])); break; case YALNIX_CUSTOM_0: SET_RET(user_ctx, sys_fork_share(user_ctx)); break; } return; }
static void syscall_handler (struct intr_frame *f) { int syscall_number; ASSERT( sizeof(syscall_number) == 4 ); // assuming x86 // The system call number is in the 32-bit word at the caller's stack pointer. memread_user(f->esp, &syscall_number, sizeof(syscall_number)); _DEBUG_PRINTF ("[DEBUG] system call, number = %d!\n", syscall_number); // Store the esp, which is needed in the page fault handler. // refer to exception.c:page_fault() (see manual 4.3.3) thread_current()->current_esp = f->esp; // Dispatch w.r.t system call number // SYS_*** constants are defined in syscall-nr.h switch (syscall_number) { case SYS_HALT: // 0 { sys_halt(); NOT_REACHED(); break; } case SYS_EXIT: // 1 { int exitcode; memread_user(f->esp + 4, &exitcode, sizeof(exitcode)); sys_exit(exitcode); NOT_REACHED(); break; } case SYS_EXEC: // 2 { void* cmdline; memread_user(f->esp + 4, &cmdline, sizeof(cmdline)); int return_code = sys_exec((const char*) cmdline); f->eax = (uint32_t) return_code; break; } case SYS_WAIT: // 3 { pid_t pid; memread_user(f->esp + 4, &pid, sizeof(pid_t)); int ret = sys_wait(pid); f->eax = (uint32_t) ret; break; } case SYS_CREATE: // 4 { const char* filename; unsigned initial_size; bool return_code; memread_user(f->esp + 4, &filename, sizeof(filename)); memread_user(f->esp + 8, &initial_size, sizeof(initial_size)); return_code = sys_create(filename, initial_size); f->eax = return_code; break; } case SYS_REMOVE: // 5 { const char* filename; bool return_code; memread_user(f->esp + 4, &filename, sizeof(filename)); return_code = sys_remove(filename); f->eax = return_code; break; } case SYS_OPEN: // 6 { const char* filename; int return_code; memread_user(f->esp + 4, &filename, sizeof(filename)); return_code = sys_open(filename); f->eax = return_code; break; } case SYS_FILESIZE: // 7 { int fd, return_code; memread_user(f->esp + 4, &fd, sizeof(fd)); return_code = sys_filesize(fd); f->eax = return_code; break; } case SYS_READ: // 8 { int fd, return_code; void *buffer; unsigned size; memread_user(f->esp + 4, &fd, sizeof(fd)); memread_user(f->esp + 8, &buffer, sizeof(buffer)); memread_user(f->esp + 12, &size, sizeof(size)); return_code = sys_read(fd, buffer, size); f->eax = (uint32_t) return_code; break; } case SYS_WRITE: // 9 { int fd, return_code; const void *buffer; unsigned size; memread_user(f->esp + 4, &fd, sizeof(fd)); memread_user(f->esp + 8, &buffer, sizeof(buffer)); memread_user(f->esp + 12, &size, sizeof(size)); return_code = sys_write(fd, buffer, size); f->eax = (uint32_t) return_code; break; } case SYS_SEEK: // 10 { int fd; unsigned position; memread_user(f->esp + 4, &fd, sizeof(fd)); memread_user(f->esp + 8, &position, sizeof(position)); sys_seek(fd, position); break; } case SYS_TELL: // 11 { int fd; unsigned return_code; memread_user(f->esp + 4, &fd, sizeof(fd)); return_code = sys_tell(fd); f->eax = (uint32_t) return_code; break; } case SYS_CLOSE: // 12 { int fd; memread_user(f->esp + 4, &fd, sizeof(fd)); sys_close(fd); break; } #ifdef VM case SYS_MMAP: // 13 { int fd; void *addr; memread_user(f->esp + 4, &fd, sizeof(fd)); memread_user(f->esp + 8, &addr, sizeof(addr)); mmapid_t ret = sys_mmap (fd, addr); f->eax = ret; break; } case SYS_MUNMAP: // 14 { mmapid_t mid; memread_user(f->esp + 4, &mid, sizeof(mid)); sys_munmap(mid); break; } #endif #ifdef FILESYS case SYS_CHDIR: // 15 { const char* filename; int return_code; memread_user(f->esp + 4, &filename, sizeof(filename)); return_code = sys_chdir(filename); f->eax = return_code; break; } case SYS_MKDIR: // 16 { const char* filename; int return_code; memread_user(f->esp + 4, &filename, sizeof(filename)); return_code = sys_mkdir(filename); f->eax = return_code; break; } case SYS_READDIR: // 17 { int fd; char *name; int return_code; memread_user(f->esp + 4, &fd, sizeof(fd)); memread_user(f->esp + 8, &name, sizeof(name)); return_code = sys_readdir(fd, name); f->eax = return_code; break; } case SYS_ISDIR: // 18 { int fd; int return_code; memread_user(f->esp + 4, &fd, sizeof(fd)); return_code = sys_isdir(fd); f->eax = return_code; break; } case SYS_INUMBER: // 19 { int fd; int return_code; memread_user(f->esp + 4, &fd, sizeof(fd)); return_code = sys_inumber(fd); f->eax = return_code; break; } #endif /* unhandled case */ default: printf("[ERROR] system call %d is unimplemented!\n", syscall_number); // ensure that waiting (parent) process should wake up and terminate. sys_exit(-1); break; } }
static void syscall_handler (struct intr_frame *f) { int sys_vector; sys_vector=*(int *)(f->esp); switch(sys_vector) { case SYS_HALT: esp_under_phys_base(f, 0); sys_halt (); break; case SYS_EXIT: if ((void *)((int *)f->esp + 1) >= PHYS_BASE) sys_exit (-1); else sys_exit (*((int *)f->esp + 1)); break; case SYS_EXEC: esp_under_phys_base(f, 1); under_phys_base (*((int **)f->esp + 1)); sys_exec (*((int **)f->esp + 1), f); break; case SYS_WAIT: esp_under_phys_base(f, 1); sys_wait (*((int *)f->esp + 1), f); break; case SYS_CREATE: if ((void*)*((int **)f->esp + 1) == NULL) sys_exit(-1); esp_under_phys_base(f, 2); under_phys_base (*((int **)f->esp + 1)); sys_create (*((int **)f->esp + 1), *((int *)f->esp + 2), f); break; case SYS_REMOVE: esp_under_phys_base(f, 1); under_phys_base (*((int **)f->esp + 1)); sys_remove (*((int **)f->esp + 1), f); break; case SYS_OPEN: if ((void*)*((int **)f->esp + 1) == NULL) sys_exit(-1); esp_under_phys_base(f, 1); under_phys_base (*((int **)f->esp + 1)); sys_open (*((int **)f->esp + 1), f); break; case SYS_FILESIZE: esp_under_phys_base(f, 1); check_fd(*((int *)f->esp + 1), -1, f); sys_filesize (*((int *)f->esp + 1), f); break; case SYS_READ: esp_under_phys_base(f, 3); under_phys_base (*((int **)f->esp + 2)); check_fd(*((int *)f->esp + 1), -1, f) sys_read (*((int *)f->esp + 1), *((int **)f->esp + 2), *((int *)f->esp + 3), f); break; case SYS_WRITE: esp_under_phys_base(f, 3); under_phys_base (*((int **)f->esp + 2)); check_fd(*((int *)f->esp + 1), -1, f) sys_write (*((int *)f->esp + 1), *((int **)f->esp + 2), *((int *)f->esp + 3), f); break; case SYS_SEEK: esp_under_phys_base(f, 2); check_fd(*((int *)f->esp + 1), 0, f) sys_seek (*((int *)f->esp + 1), *((int *)f->esp + 2), f); break; case SYS_TELL: esp_under_phys_base(f, 1); check_fd(*((int *)f->esp + 1), 0, f) sys_tell (*((int *)f->esp + 1), f); break; case SYS_CLOSE: esp_under_phys_base(f, 1); check_fd(*((int *)f->esp + 1), 0, f) sys_close (*((int *)f->esp + 1), f); break; } }
/*===========================================================================* * do_exec * *===========================================================================*/ PUBLIC int do_exec() { /* Perform the execve(name, argv, envp) call. The user library builds a * complete stack image, including pointers, args, environ, etc. The stack * is copied to a buffer inside MM, and then to the new core image. */ register struct mproc *rmp; struct mproc *sh_mp; int m, r, fd, ft, sn; static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ static char name_buf[PATH_MAX]; /* the name of the file to exec */ char *new_sp, *basename; vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp; phys_bytes tot_bytes; /* total space for program, including gap */ long sym_bytes; vir_clicks sc; struct stat s_buf; vir_bytes pc; /* Do some validity checks. */ rmp = mp; stk_bytes = (vir_bytes) stack_bytes; if (stk_bytes > ARG_MAX) return(ENOMEM); /* stack too big */ if (exec_len <= 0 || exec_len > PATH_MAX) return(EINVAL); /* Get the exec file name and see if the file is executable. */ src = (vir_bytes) exec_name; dst = (vir_bytes) name_buf; r = sys_copy(who, D, (phys_bytes) src, MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes) exec_len); if (r != OK) return(r); /* file name not in user data segment */ tell_fs(CHDIR, who, FALSE, 0); /* switch to the user's FS environ. */ fd = allowed(name_buf, &s_buf, X_BIT); /* is file executable? */ if (fd < 0) return(fd); /* file was not executable */ /* Read the file header and extract the segment sizes. */ sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, &tot_bytes, &sym_bytes, sc, &pc); if (m < 0) { close(fd); /* something wrong with header */ return(ENOEXEC); } /* Fetch the stack from the user before destroying the old core image. */ src = (vir_bytes) stack_ptr; dst = (vir_bytes) mbuf; r = sys_copy(who, D, (phys_bytes) src, MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes)stk_bytes); if (r != OK) { close(fd); /* can't fetch stack (e.g. bad virtual addr) */ return(EACCES); } /* Can the process' text be shared with that of one already running? */ sh_mp = find_share(rmp, s_buf.st_ino, s_buf.st_dev, s_buf.st_ctime); /* Allocate new memory and release old memory. Fix map and tell kernel. */ r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes); if (r != OK) { close(fd); /* insufficient core or program too big */ return(r); } /* Save file identification to allow it to be shared. */ rmp->mp_ino = s_buf.st_ino; rmp->mp_dev = s_buf.st_dev; rmp->mp_ctime = s_buf.st_ctime; /* Patch up stack and copy it from MM to new core image. */ vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT; vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT; vsp -= stk_bytes; patch_ptr(mbuf, vsp); src = (vir_bytes) mbuf; r = sys_copy(MM_PROC_NR, D, (phys_bytes) src, who, D, (phys_bytes) vsp, (phys_bytes)stk_bytes); if (r != OK) panic("do_exec stack copy err", NO_NUM); /* Read in text and data segments. */ if (sh_mp != NULL) { lseek(fd, (off_t) text_bytes, SEEK_CUR); /* shared: skip text */ } else { load_seg(fd, T, text_bytes); } load_seg(fd, D, data_bytes); #if (SHADOWING == 1) if (lseek(fd, (off_t)sym_bytes, SEEK_CUR) == (off_t) -1) ; /* error */ if (relocate(fd, (unsigned char *)mbuf) < 0) ; /* error */ pc += (vir_bytes) rp->mp_seg[T].mem_vir << CLICK_SHIFT; #endif close(fd); /* don't need exec file any more */ /* Take care of setuid/setgid bits. */ if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */ if (s_buf.st_mode & I_SET_UID_BIT) { rmp->mp_effuid = s_buf.st_uid; tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid); } if (s_buf.st_mode & I_SET_GID_BIT) { rmp->mp_effgid = s_buf.st_gid; tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid); } } /* Save offset to initial argc (for ps) */ rmp->mp_procargs = vsp; /* Fix 'mproc' fields, tell kernel that exec is done, reset caught sigs. */ for (sn = 1; sn <= _NSIG; sn++) { if (sigismember(&rmp->mp_catch, sn)) { sigdelset(&rmp->mp_catch, sn); rmp->mp_sigact[sn].sa_handler = SIG_DFL; sigemptyset(&rmp->mp_sigact[sn].sa_mask); } } rmp->mp_flags &= ~SEPARATE; /* turn off SEPARATE bit */ rmp->mp_flags |= ft; /* turn it on for separate I & D files */ new_sp = (char *) vsp; tell_fs(EXEC, who, 0, 0); /* allow FS to handle FD_CLOEXEC files */ /* System will save command line for debugging, ps(1) output, etc. */ basename = strrchr(name_buf, '/'); if (basename == NULL) basename = name_buf; else basename++; sys_exec(who, new_sp, rmp->mp_flags & TRACED, basename, pc); return(OK); }
static void syscall_handler (struct intr_frame *f) { int *sys_call; int *status; int *fd; const char **buf; int *size; const char **file; tid_t *pid; const char **cmd_line; unsigned *initial_size; unsigned *position; void **buffer; sys_call = (int*) f->esp; check_ptr(sys_call); switch(*sys_call) { case SYS_HALT: sys_halt (); break; case SYS_EXIT: status = (int *) get_arg_ptr (f->esp, 1); sys_exit(*status); NOT_REACHED(); break; case SYS_EXEC: cmd_line = (const char **) get_arg_ptr (f->esp, 1); f->eax = sys_exec (*cmd_line); break; case SYS_WAIT: pid = (tid_t *) get_arg_ptr (f->esp, 1); f->eax = sys_wait (*pid); break; case SYS_CREATE: file = (const char **) get_arg_ptr (f->esp, 1); initial_size = (unsigned *) get_arg_ptr (f->esp, 2); f->eax = sys_create (*file, *initial_size); break; case SYS_REMOVE: file = (const char **) get_arg_ptr (f->esp, 1); f->eax = sys_remove (*file); break; case SYS_OPEN: file = (const char **) get_arg_ptr(f->esp, 1); f->eax = sys_open (*file); break; case SYS_FILESIZE: fd = (int *) get_arg_ptr (f->esp, 1); f->eax = sys_filesize (*fd); break; case SYS_READ: fd = (int *) get_arg_ptr (f->esp, 1); buffer = (void **) get_arg_ptr (f->esp, 2); size = (int *) get_arg_ptr (f->esp, 3); f->eax = sys_read (*fd, *buffer, *size); break; case SYS_WRITE: fd = (int *) get_arg_ptr (f->esp, 1); buf = (const void **) get_arg_ptr (f->esp, 2); size = (int *) get_arg_ptr (f->esp, 3); f->eax = sys_write (*fd, *buf, *size); break; case SYS_SEEK: fd = (int *) get_arg_ptr (f->esp, 1); position = (unsigned *) get_arg_ptr (f->esp, 2); sys_seek (*fd, *position); break; case SYS_TELL: fd = (int *) get_arg_ptr (f->esp, 1); f->eax = sys_tell (*fd); break; case SYS_CLOSE: fd = (int *) get_arg_ptr (f->esp, 1); sys_close (*fd); break; default: printf ("Unrecognized system call!\n"); thread_exit (); } }