diff --git a/lecture_note/docs/pintos/proj2.md b/lecture_note/docs/pintos/proj2.md index b1cf7fc..be9a979 100644 --- a/lecture_note/docs/pintos/proj2.md +++ b/lecture_note/docs/pintos/proj2.md @@ -7,7 +7,7 @@ - Task1 : print termination messages - Task2 : argument passing - Task3 : system calls - - Task4 : deny writes to executables + - Task4 : ## 分析 @@ -30,10 +30,12 @@ msg ("begin"); msg ("argc = %d", argc); for (i = 0; i <= argc; i++) if (argv[i] != NULL) - msg ("argv[%d] = '%s'", i, argv[i]); + msg ("argv[%d] = '%s'", i, argv[i]); // 需要把 arg 分隔开 else msg ("argv[%d] = null", i); msg ("end"); + +return 0; // 我该怎么得到你, 亲爱的返回值? ``` 主要内容为打印命令行参数, 也就是需要实现为 user program 传参. @@ -50,4 +52,26 @@ process_wait (tid_t child_tid UNUSED) } ``` -按照注释里的内容, 这个函数作用是等待编号 `child_tid` 线程的运行结果, 如果被系统中止/传入的 `tid` 不存在/则返回 `-1`, 否则返回 \ No newline at end of file +按照注释里的内容, 这个函数作用是等待编号 `child_tid` 线程的运行结果, 如果那个线程被系统中止/传入的 `tid` 不存在/传入的 `tid` 代表的进程不是目前线程的子进程/这个线程已经有一个 `process_wait()` 在等待它则返回 `-1`, 否则返回它的退出情况. + +## Task 1 + +在一个进程退出时输出中止信息 (名称, exit code) + +在 `process.c` 内查找发现有一个 `process_exit()`, 用于释放一个进程分配的资源, 这个函数在 `thread_exit()` 被调用, 由于 pintos 的一个进程下没有多线程, 所以直接用该线程的 exit 代表. + +于是需要在 `process_exit()` 内加上信息打印. + +进程名称来自线程名称, 在 `process_excute()` 内打印, 发现 `file_name` 不仅传入了要运行的文件的名称, 还有运行参数, 是一行完整的指令, 需要手动按空格分离函数名和以空格 (可能多个空格) 分隔开的每个 command line args. + +`process_execute()` 内, `palloc_get_page(0)` 获得了 kernel pool 的一个 page, 存储完整的命令, 在 `start_process()` 中 `load()` 加载可执行文件完毕后将其释放, `thread` 中的 `name` 使用 `memcpy` 复制到字符数组, 而 command line args 需要直接压到栈里面, 所以说可以通过在前面分配, 在 `start_process()` 内释放的形式临时保存命令行语句. + +这样, 在 `process_execute()` 时直接分割出可执行文件名称, 作为线程名称即可. + +你说得对, 但是我返回值呢? + +做不了一点, 看下一个 task. + +## Task 2 + +为 user program 传参. diff --git a/pintos/src/userprog/process.c b/pintos/src/userprog/process.c index c0e5215..bd307de 100644 --- a/pintos/src/userprog/process.c +++ b/pintos/src/userprog/process.c @@ -26,22 +26,32 @@ static bool load (const char *cmdline, void (**eip) (void), void **esp); before process_execute() returns. Returns the new process's thread id, or TID_ERROR if the thread cannot be created. */ tid_t -process_execute (const char *file_name) +process_execute (const char *command_args) { - char *fn_copy; + char *ca_copy_1, *ca_copy_2; tid_t tid; - /* Make a copy of FILE_NAME. - Otherwise there's a race between the caller and load(). */ - fn_copy = palloc_get_page (0); - if (fn_copy == NULL) + char *prog_name, *save_ptr; + + /* Make two copies of COMMAND_ARGS. + Otherwise there's a race between the caller and load(). + One copy for executable file name, the other for args. */ + ca_copy_1 = palloc_get_page (0); + ca_copy_2 = palloc_get_page (0); + if (ca_copy_1 == NULL || ca_copy_2 == NULL) return TID_ERROR; - strlcpy (fn_copy, file_name, PGSIZE); + strlcpy (ca_copy_1, command_args, PGSIZE); + strlcpy (ca_copy_2, command_args, PGSIZE); + prog_name = strtok_r (ca_copy_1, " ", &save_ptr); /* Create a new thread to execute FILE_NAME. */ - tid = thread_create (file_name, PRI_DEFAULT, start_process, fn_copy); + tid = thread_create (prog_name, PRI_DEFAULT, start_process, ca_copy_2); + printf ("NONONONO\n"); if (tid == TID_ERROR) - palloc_free_page (fn_copy); + { + palloc_free_page (ca_copy_1); + palloc_free_page (ca_copy_2); + } return tid; } @@ -51,6 +61,9 @@ static void start_process (void *file_name_) { char *file_name = file_name_; + + printf ("file name : %s\n", file_name); + struct intr_frame if_; bool success; @@ -59,12 +72,17 @@ start_process (void *file_name_) if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG; if_.cs = SEL_UCSEG; if_.eflags = FLAG_IF | FLAG_MBS; + + printf ("you should load\n"); + success = load (file_name, &if_.eip, &if_.esp); + printf ("start loading\n"); /* If load failed, quit. */ palloc_free_page (file_name); if (!success) thread_exit (); + printf ("end loading\n"); /* Start the user process by simulating a return from an interrupt, implemented by intr_exit (in @@ -114,6 +132,8 @@ process_exit (void) pagedir_activate (NULL); pagedir_destroy (pd); } + int not_implemented = 0; + printf ("%s: exit(%d)\n", cur->name, not_implemented); } /* Sets up the CPU for running user code in the current