[Krafton Jungle] PintOS 2.0.0
크래프톤 정글 PintOS
 
Loading...
Searching...
No Matches
process.c File Reference
#include "userprog/process.h"
#include <debug.h>
#include <inttypes.h>
#include <round.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "userprog/gdt.h"
#include "userprog/tss.h"
#include "filesys/directory.h"
#include "filesys/file.h"
#include "filesys/filesys.h"
#include "threads/flags.h"
#include "threads/init.h"
#include "threads/interrupt.h"
#include "threads/palloc.h"
#include "threads/thread.h"
#include "threads/mmu.h"
#include "threads/vaddr.h"
#include "intrinsic.h"
#include "lib/user/syscall.h"
Include dependency graph for process.c:

Classes

struct  ELF64_hdr
 
struct  ELF64_PHDR
 

Macros

#define EI_NIDENT   16
 
#define PT_NULL   0 /* Ignore. */
 
#define PT_LOAD   1 /* Loadable segment. */
 
#define PT_DYNAMIC   2 /* Dynamic linking info. */
 
#define PT_INTERP   3 /* Name of dynamic loader. */
 
#define PT_NOTE   4 /* Auxiliary info. */
 
#define PT_SHLIB   5 /* Reserved. */
 
#define PT_PHDR   6 /* Program header table. */
 
#define PT_STACK   0x6474e551 /* Stack segment. */
 
#define PF_X   1 /* Executable. */
 
#define PF_W   2 /* Writable. */
 
#define PF_R   4 /* Readable. */
 
#define ELF   ELF64_hdr
 
#define Phdr   ELF64_PHDR
 

Functions

static void process_cleanup (void)
 
static bool load (const char *file_name, struct intr_frame *if_)
 
static void initd (void *f_name)
 
static void __do_fork (void *)
 
static void argument_parse (char *file_name, int *argc_ptr, char *argv[])
 
static void argument_stack (int argc, char **argv, struct intr_frame *if_)
 
struct threadget_child_process (int pid)
 
static void process_init (void)
 
tid_t process_create_initd (const char *file_name)
 
tid_t process_fork (const char *name, struct intr_frame *if_ UNUSED)
 
static bool duplicate_pte (uint64_t *pte, void *va, void *aux)
 
int process_exec (void *f_name)
 
int process_wait (tid_t child_tid UNUSED)
 
void process_exit (void)
 
void process_activate (struct thread *next)
 
bool setup_stack (struct intr_frame *if_)
 
static bool validate_segment (const struct Phdr *, struct file *)
 
static bool load_segment (struct file *file, off_t ofs, uint8_t *upage, uint32_t read_bytes, uint32_t zero_bytes, bool writable)
 
static bool install_page (void *upage, void *kpage, bool writable)
 

Macro Definition Documentation

◆ EI_NIDENT

#define EI_NIDENT   16

◆ ELF

#define ELF   ELF64_hdr

◆ PF_R

#define PF_R   4 /* Readable. */

◆ PF_W

#define PF_W   2 /* Writable. */

◆ PF_X

#define PF_X   1 /* Executable. */

◆ Phdr

#define Phdr   ELF64_PHDR

◆ PT_DYNAMIC

#define PT_DYNAMIC   2 /* Dynamic linking info. */

◆ PT_INTERP

#define PT_INTERP   3 /* Name of dynamic loader. */

◆ PT_LOAD

#define PT_LOAD   1 /* Loadable segment. */

◆ PT_NOTE

#define PT_NOTE   4 /* Auxiliary info. */

◆ PT_NULL

#define PT_NULL   0 /* Ignore. */

◆ PT_PHDR

#define PT_PHDR   6 /* Program header table. */

◆ PT_SHLIB

#define PT_SHLIB   5 /* Reserved. */

◆ PT_STACK

#define PT_STACK   0x6474e551 /* Stack segment. */

Function Documentation

◆ __do_fork()

static void __do_fork ( void *  aux)
static
171 {
172 struct intr_frame if_;
173 struct thread *parent = (struct thread *) aux; // 부모 프로세스
174 struct thread *current = thread_current (); // 새로 생성된 자식 프로세스
175 /* TODO: somehow pass the parent_if. (i.e. process_fork()'s if_) */
176 /* TODO: process_fork의 두 번째 인자인 parent_if를 전달한다. */
177 struct intr_frame *parent_if;
178 bool succ = true;
179
180 parent_if = &parent->parent_if; // process_fork에서 복사 해두었던 intr_frame
181 /* 1. Read the cpu context to local stack. */
182 /* 1. 부모의 인터럽트 프레임을 읽어온다.(if_로 복사) */
183 memcpy (&if_, parent_if, sizeof (struct intr_frame));
184
185 if_.R.rax = 0; // fork 시스템 콜의 결과로 자식 프로세스는 0을 리턴해야하므로 0을 넣어준다.
186
187 /* 2. Duplicate PT */
188 /* 2. 페이지 테이블을 복제한다. */
189 current->pml4 = pml4_create(); // 부모의 pte를 복사하기 위해 페이지 테이블을 생성한다.
190 if (current->pml4 == NULL)
191 goto error;
192
193 process_activate (current);
194#ifdef VM
196 if (!supplemental_page_table_copy (&current->spt, &parent->spt))
197 goto error;
198#else
199 // "pml4_for_each" : Apply FUNC to each available pte entries including kernel's.
200 if (!pml4_for_each (parent->pml4, duplicate_pte, parent)) // "duplicate_pte" : 페이지 테이블을 복제하는 함수(부모 -> 자식)
201 goto error;
202#endif
203
204 /* TODO: Your code goes here.
205 * TODO: Hint) To duplicate the file object, use `file_duplicate`
206 * TODO: in include/filesys/file.h. Note that parent should not return
207 * TODO: from the fork() until this function successfully duplicates
208 * TODO: the resources of parent.*/
209 /*
210 * 파일 객체를 복제하려면 'file_duplicate'를 사용하라.
211 * 이 함수가 부모의 리소스를 성공적으로 복제할 때까지 부모 프로세스는 fork로 부터 리턴할 수 없다.
212 */
213 if (parent->next_fd == FDCOUNT_LIMIT)
214 goto error;
215
216 // 부모의 fdt를 자식의 fdt로 복사한다.
217 for (int fd = 2; fd < FDCOUNT_LIMIT; fd++) {
218 struct file *file = parent->fdt[fd];
219 if (file == NULL) // fd엔트리가 없는 상태에는 그냥 건너뛴다.
220 continue;
221 current->fdt[fd] = file_duplicate (file);
222 }
223
224 current->next_fd = parent->next_fd; // 부모의 next_fd를 자식의 next_fd로 옮겨준다.
225 sema_up(&current->fork_sema); // fork가 정상적으로 완료되었으므로 현재 wait중인 parent를 다시 실행 가능 상태로 만든다.
226
227 /* Finally, switch to the newly created process. */
228 /* 새로 생성된 프로세스에 대해 컨텍스트 스위치를 수행한다. */
229 if (succ)
230 do_iret (&if_);
231error: // 제대로 복제가 안된 상태 - TID_ERROR 리턴
232 sema_up(&current->fork_sema);
234 // thread_exit ();
235}
struct file * file_duplicate(struct file *file)
Definition: file.c:41
void exit(int status) NO_RETURN
현재 프로세스를 종료시키는 시스템 콜
Definition: syscall.c:173
uint64_t * pml4_create(void)
Definition: mmu.c:96
bool pml4_for_each(uint64_t *, pte_for_each_func *, void *)
Definition: mmu.c:148
static bool duplicate_pte(uint64_t *pte, void *va, void *aux)
Definition: process.c:118
void process_activate(struct thread *next)
Definition: process.c:379
#define NULL
Definition: stddef.h:4
void * memcpy(void *, const void *, size_t)
Definition: string.c:7
Definition: file.c:7
Definition: interrupt.h:37
Definition: thread.h:100
int next_fd
Definition: thread.h:123
uint64_t * pml4
Definition: thread.h:121
struct supplemental_page_table spt
Definition: thread.h:143
struct intr_frame parent_if
Definition: thread.h:126
struct file ** fdt
Definition: thread.h:122
struct semaphore fork_sema
Definition: thread.h:133
void sema_up(struct semaphore *)
Definition: synch.c:114
struct thread * thread_current(void)
Definition: thread.c:301
#define TID_ERROR
Definition: thread.h:26
void do_iret(struct intr_frame *tf)
Definition: thread.c:577
#define FDCOUNT_LIMIT
Definition: thread.h:35
bool supplemental_page_table_copy(struct supplemental_page_table *dst, struct supplemental_page_table *src)
void supplemental_page_table_init(struct supplemental_page_table *spt)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ argument_parse()

static void argument_parse ( char *  file_name,
int *  argc_ptr,
char *  argv[] 
)
static
865 {
866 char *token, *save_ptr;
867
868 for (token = strtok_r(file_name, " ", &save_ptr); token != NULL; token = strtok_r (NULL, " ", &save_ptr))
869 argv[(*argc_ptr)++] = token;
870
871 argv[*argc_ptr] = token;
872}
char * strtok_r(char *, const char *, char **)
Definition: string.c:219
Here is the call graph for this function:
Here is the caller graph for this function:

◆ argument_stack()

static void argument_stack ( int  argc,
char **  argv,
struct intr_frame if_ 
)
static
874 {
875 char *argv_addr[128];
876 for (int i = argc - 1; i >= 0; i--){ // argument
877 if_->rsp -= strlen(argv[i]) + 1;
878 // if_->rsp = argv[i];
879 memcpy(if_->rsp, argv[i], strlen(argv[i]) + 1); // *(if_->rsp) = *argv[1]; 'if_->rsp'의 크기를 몰라서 이렇게 하면 안됨
880 argv_addr[i] = if_->rsp;
881 }
882
883 while (if_->rsp % 8 > 0){ // word-aline padding
884 if_->rsp -= 1;
885 memset(if_->rsp, 0, 1);
886 }
887
888 if_->rsp -= sizeof(char *);
889 memset(if_->rsp, 0, sizeof(char *));
890
891 for (int i = argc - 1; i >= 0; i--){
892 if_->rsp -= sizeof(char *);
893 // if_->rsp = argv_addr[i];
894 memcpy(if_->rsp, &argv_addr[i], sizeof(char *));
895 }
896
897 if_->rsp -= sizeof(char *);
898 memset(if_->rsp, 0, sizeof(char *));
899
900 if_->R.rdi = argc;
901 if_->R.rsi = if_->rsp + 8;
902}
size_t strlen(const char *)
Definition: string.c:271
void * memset(void *, int, size_t)
Definition: string.c:258
uint64_t rdi
Definition: interrupt.h:29
uint64_t rsi
Definition: interrupt.h:28
struct gp_registers R
Definition: interrupt.h:40
uintptr_t rsp
Definition: interrupt.h:60
Here is the call graph for this function:
Here is the caller graph for this function:

◆ duplicate_pte()

static bool duplicate_pte ( uint64_t pte,
void *  va,
void *  aux 
)
static
118 {
119 struct thread *current = thread_current ();
120 struct thread *parent = (struct thread *) aux;
121 void *parent_page;
122 void *newpage;
123 bool writable;
124
125 /* 1. TODO: If the parent_page is kernel page, then return immediately. */
126 if (is_kernel_vaddr(va))
127 {
128 return true;
129 }
130 /* 2. Resolve VA from the parent's page map level 4. */
131 parent_page = pml4_get_page (parent->pml4, va);
132
133 if (parent_page == NULL)
134 {
135 return false;
136 }
137
138 /* 3. TODO: Allocate new PAL_USER page for the child and set result to
139 * TODO: NEWPAGE. */
140
141 newpage = palloc_get_page(PAL_USER);
142 if (newpage == NULL)
143 {
144 return false;
145 }
146
147 /* 4. TODO: Duplicate parent's page to the new page and
148 * TODO: check whether parent's page is writable or not (set WRITABLE
149 * TODO: according to the result). */
150 memcpy(newpage,parent_page, PGSIZE);
151 writable = is_writable(pte);
152
153 /* 5. Add new page to child's page table at address VA with WRITABLE
154 * permission. */
155 if (!pml4_set_page (current->pml4, va, newpage, writable)) {
156 /* 6. TODO: if fail to insert page, do error handling. */
157 return false;
158 }
159 return true;
160}
bool pml4_set_page(uint64_t *pml4, void *upage, void *kpage, bool rw)
Definition: mmu.c:240
void * pml4_get_page(uint64_t *pml4, const void *upage)
Definition: mmu.c:214
#define is_writable(pte)
Definition: mmu.h:23
@ PAL_USER
Definition: palloc.h:11
void * palloc_get_page(enum palloc_flags)
Definition: palloc.c:301
#define is_kernel_vaddr(vaddr)
Definition: vaddr.h:44
#define PGSIZE
Definition: vaddr.h:20
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_child_process()

struct thread * get_child_process ( int  pid)
907 {
908 struct thread *curr = thread_current();
909 struct list *child_list = &curr->child_list;
910
911 // 자식 리스트를 순회하면서 프로세스 디스크립터 검색
912 for (struct list_elem *e = list_begin(child_list); e != list_end(child_list); e = list_next(e))
913 {
914 struct thread *t = list_entry(e, struct thread, child_elem);
915 if (t->tid == pid) // 해당 pid가 존재하면 프로세스 디스크립터 리턴
916 return t;
917 }
918 return NULL; // 리스트에 존재하지 않으면 NULL
919}
struct list_elem * list_begin(struct list *)
Definition: list.c:68
struct list_elem * list_next(struct list_elem *)
Definition: list.c:77
struct list_elem * list_end(struct list *)
Definition: list.c:88
#define list_entry(LIST_ELEM, STRUCT, MEMBER)
Definition: list.h:103
Definition: list.h:87
Definition: list.h:93
struct list_elem child_elem
Definition: thread.h:128
tid_t tid
Definition: thread.h:102
struct list child_list
Definition: thread.h:127
Here is the call graph for this function:
Here is the caller graph for this function:

◆ initd()

static void initd ( void *  f_name)
static
73 {
74// CHECK [process_exec -> supplemental_page_table_init]의 중복 선언으로 인한 코드 제거
75#ifdef VM
77#endif
78
79 process_init ();
80
81 if (process_exec (f_name) < 0)
82 PANIC("Fail to launch initd\n");
83 NOT_REACHED ();
84}
#define NOT_REACHED()
Definition: debug.h:34
#define PANIC(...)
Definition: debug.h:14
int process_exec(void *f_name)
Definition: process.c:241
static void process_init(void)
Definition: process.c:41
Here is the call graph for this function:
Here is the caller graph for this function:

◆ install_page()

static bool install_page ( void *  upage,
void *  kpage,
bool  writable 
)
static
698 {
699 struct thread *t = thread_current ();
700
701 /* Verify that there's not already a page at that virtual
702 * address, then map our page there. */
703 return (pml4_get_page (t->pml4, upage) == NULL
704 && pml4_set_page (t->pml4, upage, kpage, writable));
705}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ load()

static bool load ( const char *  file_name,
struct intr_frame if_ 
)
static
451 {
452 struct thread *t = thread_current ();
453 struct ELF ehdr;
454 struct file *file = NULL;
455 off_t file_ofs;
456 bool success = false;
457 int i;
458
459 /* Allocate and activate page directory. */
460 t->pml4 = pml4_create ();
461 if (t->pml4 == NULL)
462 goto done;
464
465 /* Open executable file. */
466 file = filesys_open (file_name);
467 if (file == NULL) {
468 printf ("load: %s: open failed\n", file_name);
469 goto done;
470 }
471
472 t->running = file;
473
474 file_deny_write(file); // 현재 오픈한 파일에 접근 못하게 함
475
476 /* Read and verify executable header. */
477 if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr
478 || memcmp (ehdr.e_ident, "\177ELF\2\1\1", 7)
479 || ehdr.e_type != 2
480 || ehdr.e_machine != 0x3E // amd64
481 || ehdr.e_version != 1
482 || ehdr.e_phentsize != sizeof (struct Phdr)
483 || ehdr.e_phnum > 1024) {
484 printf ("load: %s: error loading executable\n", file_name);
485 goto done;
486 }
487
488 /* Read program headers. */
489 file_ofs = ehdr.e_phoff;
490 for (i = 0; i < ehdr.e_phnum; i++) {
491 struct Phdr phdr;
492
493 if (file_ofs < 0 || file_ofs > file_length (file))
494 goto done;
495 file_seek (file, file_ofs);
496
497 if (file_read (file, &phdr, sizeof phdr) != sizeof phdr)
498 goto done;
499 file_ofs += sizeof phdr;
500 switch (phdr.p_type) {
501 case PT_NULL:
502 case PT_NOTE:
503 case PT_PHDR:
504 case PT_STACK:
505 default:
506 /* Ignore this segment. */
507 break;
508 case PT_DYNAMIC:
509 case PT_INTERP:
510 case PT_SHLIB:
511 goto done;
512 case PT_LOAD:
513 if (validate_segment (&phdr, file)) {
514 bool writable = (phdr.p_flags & PF_W) != 0;
515 uint64_t file_page = phdr.p_offset & ~PGMASK;
516 uint64_t mem_page = phdr.p_vaddr & ~PGMASK;
517 uint64_t page_offset = phdr.p_vaddr & PGMASK;
518 uint32_t read_bytes, zero_bytes;
519 if (phdr.p_filesz > 0) {
520 /* Normal segment.
521 * Read initial part from disk and zero the rest. */
522 read_bytes = page_offset + phdr.p_filesz;
523 zero_bytes = (ROUND_UP (page_offset + phdr.p_memsz, PGSIZE)
524 - read_bytes);
525 } else {
526 /* Entirely zero.
527 * Don't read anything from disk. */
528 read_bytes = 0;
529 zero_bytes = ROUND_UP (page_offset + phdr.p_memsz, PGSIZE);
530 }
531 if (!load_segment (file, file_page, (void *) mem_page,
532 read_bytes, zero_bytes, writable))
533 goto done;
534 }
535 else
536 goto done;
537 break;
538 }
539 }
540
541 /* Set up stack. */
542 if (!setup_stack (if_))
543 goto done;
544
545 /* Start address. */
546 if_->rip = ehdr.e_entry;
547
548 /* TODO: Your code goes here.
549 * TODO: Implement argument passing (see project2/argument_passing.html). */
550 /* 커맨드 라인을 파싱한다. */
551 // argument_stack(argc, argv, if_->rsp, &if_);
552 // argument_stack(arg_list, token_count, &if_);
553
554 success = true;
555
556done:
557 /* We arrive here whether the load is successful or not. */
558 // file_close (file);
559 return success;
560}
void file_seek(struct file *file, off_t new_pos)
Definition: file.c:149
off_t file_length(struct file *file)
Definition: file.c:141
void file_deny_write(struct file *file)
Definition: file.c:119
off_t file_read(struct file *file, void *buffer, off_t size)
Definition: file.c:73
struct file * filesys_open(const char *name)
Definition: filesys.c:81
int32_t off_t
Definition: off_t.h:9
#define PT_STACK
Definition: process.c:400
#define PF_W
Definition: process.c:403
#define PT_DYNAMIC
Definition: process.c:395
static bool load_segment(struct file *file, off_t ofs, uint8_t *upage, uint32_t read_bytes, uint32_t zero_bytes, bool writable)
Definition: process.c:630
bool setup_stack(struct intr_frame *if_)
Definition: process.c:673
#define PT_PHDR
Definition: process.c:399
static bool validate_segment(const struct Phdr *, struct file *)
Definition: process.c:566
#define ELF
Definition: process.c:437
#define PT_NOTE
Definition: process.c:397
#define PT_LOAD
Definition: process.c:394
#define PT_NULL
Definition: process.c:393
#define Phdr
Definition: process.c:438
#define PT_INTERP
Definition: process.c:396
#define PT_SHLIB
Definition: process.c:398
#define ROUND_UP(X, STEP)
Definition: round.h:6
unsigned int uint32_t
Definition: stdint.h:26
unsigned long long int uint64_t
Definition: stdint.h:29
int printf(const char *,...) PRINTF_FORMAT(1
int memcmp(const void *, const void *, size_t)
Definition: string.c:48
Definition: file.h:9
uintptr_t rip
Definition: interrupt.h:55
struct file * running
Definition: thread.h:130
#define PGMASK
Definition: vaddr.h:21
Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_segment()

static bool load_segment ( struct file file,
off_t  ofs,
uint8_t upage,
uint32_t  read_bytes,
uint32_t  zero_bytes,
bool  writable 
)
static
631 {
632 ASSERT ((read_bytes + zero_bytes) % PGSIZE == 0);
633 ASSERT (pg_ofs (upage) == 0);
634 ASSERT (ofs % PGSIZE == 0);
635
636 file_seek (file, ofs);
637 while (read_bytes > 0 || zero_bytes > 0) {
638 /* Do calculate how to fill this page.
639 * We will read PAGE_READ_BYTES bytes from FILE
640 * and zero the final PAGE_ZERO_BYTES bytes. */
641 size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
642 size_t page_zero_bytes = PGSIZE - page_read_bytes;
643
644 /* Get a page of memory. */
646 if (kpage == NULL)
647 return false;
648
649 /* Load this page. */
650 if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes) {
651 palloc_free_page (kpage);
652 return false;
653 }
654 memset (kpage + page_read_bytes, 0, page_zero_bytes);
655
656 /* Add the page to the process's address space. */
657 if (!install_page (upage, kpage, writable)) {
658 printf("fail\n");
659 palloc_free_page (kpage);
660 return false;
661 }
662
663 /* Advance. */
664 read_bytes -= page_read_bytes;
665 zero_bytes -= page_zero_bytes;
666 upage += PGSIZE;
667 }
668 return true;
669}
#define ASSERT(CONDITION)
Definition: debug.h:30
void palloc_free_page(void *)
Definition: palloc.c:333
static bool install_page(void *upage, void *kpage, bool writable)
Definition: process.c:698
unsigned char uint8_t
Definition: stdint.h:20
#define pg_ofs(va)
Definition: vaddr.h:24
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_activate()

void process_activate ( struct thread next)
379 {
380 /* Activate thread's page tables. */
381 pml4_activate (next->pml4);
382
383 /* Set thread's kernel stack for use in processing interrupts. */
385}
static int next(int pos)
Definition: intq.c:74
void pml4_activate(uint64_t *pml4)
Definition: mmu.c:205
void tss_update(struct thread *next)
Definition: tss.c:71
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_cleanup()

static void process_cleanup ( void  )
static
350 {
351 struct thread *curr = thread_current ();
352
353#ifdef VM
354 if(!hash_empty(&curr->spt.spt_hash)) // ? threads tests all fail
356#endif
357
358 uint64_t *pml4;
359 /* Destroy the current process's page directory and switch back
360 * to the kernel-only page directory. */
361 pml4 = curr->pml4;
362 if (pml4 != NULL) {
363 /* Correct ordering here is crucial. We must set
364 * cur->pagedir to NULL before switching page directories,
365 * so that a timer interrupt can't switch back to the
366 * process page directory. We must activate the base page
367 * directory before destroying the process's page
368 * directory, or our active page directory will be one
369 * that's been freed (and cleared). */
370 curr->pml4 = NULL;
373 }
374}
bool hash_empty(struct hash *)
Definition: hash.c:236
void pml4_destroy(uint64_t *pml4)
Definition: mmu.c:190
struct hash spt_hash
Definition: vm.h:117
void supplemental_page_table_kill(struct supplemental_page_table *spt)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_create_initd()

tid_t process_create_initd ( const char *  file_name)
52 {
53 char *fn_copy, *save_ptr;
54 tid_t tid;
55
56 /* Make a copy of FILE_NAME.
57 * Otherwise there's a race between the caller and load(). */
58 fn_copy = palloc_get_page (0);
59 if (fn_copy == NULL)
60 return TID_ERROR;
61 strlcpy (fn_copy, file_name, PGSIZE);
62 /* Create a new thread to execute FILE_NAME. */
63 strtok_r (file_name, " ", &save_ptr); // 실행 파일 이름 파싱
64 // ↳해당 라인을 추가하지 않으면 커맨드 라인 전체가 스레드 이름으로 지정된다.
65 tid = thread_create (file_name, PRI_DEFAULT, initd, fn_copy);
66 if (tid == TID_ERROR)
67 palloc_free_page (fn_copy);
68 return tid;
69}
static void initd(void *f_name)
Definition: process.c:73
size_t strlcpy(char *, const char *, size_t)
Definition: string.c:302
#define PRI_DEFAULT
Definition: thread.h:30
int tid_t
Definition: thread.h:25
tid_t thread_create(const char *name, int priority, thread_func *, void *)
Definition: thread.c:197
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_exec()

int process_exec ( void *  f_name)
241 {
242 char *file_name = f_name; // 실행할 파일 이름(argv[0])
243 // char *file_name_copy[48];
244 bool success;
245
246 /* We cannot use the intr_frame in the thread structure.
247 * This is because when current thread rescheduled,
248 * it stores the execution information to the member. */
249 struct intr_frame _if;
250 _if.ds = _if.es = _if.ss = SEL_UDSEG;
251 _if.cs = SEL_UCSEG;
252 _if.eflags = FLAG_IF | FLAG_MBS;
253
254 int argc = 0;
255 char *argv[128]; // 64bit computer(uint64_t : 8byte)
256
257 /* We first kill the current context */
259
260 /*-------------------------[P3]hash table---------------------------------*/
261 #ifdef VM
263 #endif
264 /*-------------------------[P3]hash table---------------------------------*/
265
266 /* 커맨드 라인을 파싱한다. */
267 argument_parse(file_name, &argc, argv);
268
269 /* And then load the binary */
270 success = load (file_name, &_if);
271
272
273 /* If load failed, quit. */
274 if (!success){
275 palloc_free_page (file_name);
276 return -1;
277 }
278
279 argument_stack(argc, argv, &_if); // argc, argv로 커맨드 라인 파싱
280 // hex_dump(_if.rsp, _if.rsp, USER_STACK - _if.rsp, true); // 메모리에 적재된 상태 출력
281 palloc_free_page (file_name);
282
283 /* Start switched process. */
284 do_iret (&_if);
285 NOT_REACHED ();
286}
#define FLAG_IF
Definition: flags.h:6
#define FLAG_MBS
Definition: flags.h:4
#define SEL_UCSEG
Definition: loader.h:39
#define SEL_UDSEG
Definition: loader.h:38
static bool load(const char *file_name, struct intr_frame *if_)
Definition: process.c:451
static void process_cleanup(void)
Definition: process.c:350
static void argument_parse(char *file_name, int *argc_ptr, char *argv[])
Definition: process.c:865
static void argument_stack(int argc, char **argv, struct intr_frame *if_)
Definition: process.c:874
uint16_t ds
Definition: interrupt.h:44
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_exit()

void process_exit ( void  )
328 {
329 struct thread *curr = thread_current ();
330 /* TODO: Your code goes here.
331 * TODO: Implement process termination message (see
332 * TODO: project2/process_termination.html).
333 * TODO: We recommend you to implement process resource cleanup here. */
334
335 for (int i = 0; i < FDCOUNT_LIMIT; i++) // 프로세스 종료 시, 해당 프로세스의 fdt의 모든 값을 0으로 만들어준다.
336 close(i);
337 palloc_free_multiple(curr->fdt, FDT_PAGES); // fd table 메모리 해제
338
339 file_close(curr->running); // 현재 프로세스가 실행중인 파일을 종료한다.
340
342
343 sema_up(&curr->wait_sema); // 부모 프로세스가 자식 프로세스의 종료상태를 확인하게 한다.
344 thread_sleep(500);
345 // sema_down(&curr->free_sema); // 부모 프로세스가 자식 프로세스의 종료 상태를 받을때 까지 대기한다.
346}
void file_close(struct file *file)
Definition: file.c:53
void close(int fd)
열린 파일을 닫는 시스템 콜
Definition: syscall.c:392
void palloc_free_multiple(void *, size_t page_cnt)
Definition: palloc.c:307
struct semaphore wait_sema
Definition: thread.h:135
void thread_sleep(int64_t ticks)
Definition: thread.c:365
#define FDT_PAGES
Definition: thread.h:34
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_fork()

tid_t process_fork ( const char *  name,
struct intr_frame *if_  UNUSED 
)
93 {
94 /* Clone current thread to new thread.*/
95
96 struct thread *curr = thread_current();
97
98 memcpy(&curr->parent_if, if_, sizeof(struct intr_frame)); // 전달받은 intr_frame을 parent_if필드에 복사한다.
99 // ↳ '__do_fork' 에서 자식 프로세스에 부모의 컨텍스트 정보를 복사하기 위함(부모의 인터럽트 프레임을 찾는 용도로 사용)
100
101 tid_t tid = thread_create(name, curr->priority, __do_fork, curr); // __do_fork를 실행하는 스레드 생성, 현재 스레드를 인자로 넘겨준다.
102 if (tid == TID_ERROR)
103 return TID_ERROR;
104
105 struct thread *child = get_child_process(tid);
106 sema_down(&child->fork_sema); // 자식 프로세스가 로드될 때까지 부모 프로세스는 대기한다.
107 if (child->exit_status == TID_ERROR)
108 return TID_ERROR;
109
110 return tid; // 부모 프로세스의 리턴값 : 생성한 자식 프로세스의 tid
111}
static void __do_fork(void *)
Definition: process.c:171
struct thread * get_child_process(int pid)
Definition: process.c:907
int priority
Definition: thread.h:105
char name[16]
Definition: thread.h:104
int exit_status
Definition: thread.h:131
void sema_down(struct semaphore *)
Definition: synch.c:68
Here is the call graph for this function:

◆ process_init()

static void process_init ( void  )
static
41 {
42 struct thread *current = thread_current ();
43}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_wait()

int process_wait ( tid_t child_tid  UNUSED)
303 {
304 /* XXX: Hint) The pintos exit if process_wait (initd), we recommend you
305 * XXX: to add infinite loop here before
306 * XXX: implementing the process_wait. */
307 // for(int i = 0 ; i<10000000; i++);
308
309 // return -1;
310 struct thread *child = get_child_process(child_tid);
311
312 if(child == NULL) // 해당 자식이 존재하지 않는다면 -1 리턴
313 return -1;
314
315 sema_down(&child->wait_sema); // 자식 프로세스가 종료할 때까지 대기한다.
316 // 컨텍스트 스위칭 발생
317
318 int exit_status = child->exit_status; // 자식으로 부터 종료인자를 전달 받고 리스트에서 삭제한다.
319 list_remove(&child->child_elem);
320
321 // sema_up(&child->free_sema); // 자식 프로세스 종료 상태를 받은 후 자식 프로세스를 종료하게 한다.
322
323 return exit_status;
324}
struct list_elem * list_remove(struct list_elem *)
Definition: list.c:241
Here is the call graph for this function:

◆ setup_stack()

bool setup_stack ( struct intr_frame if_)
673 {
674 uint8_t *kpage;
675 bool success = false;
676
678 if (kpage != NULL) {
679 success = install_page (((uint8_t *) USER_STACK) - PGSIZE, kpage, true);
680 if (success)
681 if_->rsp = USER_STACK;
682 else
683 palloc_free_page (kpage);
684 }
685 return success;
686}
@ PAL_ZERO
Definition: palloc.h:10
#define USER_STACK
Definition: vaddr.h:38
Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_segment()

static bool validate_segment ( const struct Phdr phdr,
struct file file 
)
static
566 {
567 /* p_offset and p_vaddr must have the same page offset. */
568 if ((phdr->p_offset & PGMASK) != (phdr->p_vaddr & PGMASK))
569 return false;
570
571 /* p_offset must point within FILE. */
572 if (phdr->p_offset > (uint64_t) file_length (file))
573 return false;
574
575 /* p_memsz must be at least as big as p_filesz. */
576 if (phdr->p_memsz < phdr->p_filesz)
577 return false;
578
579 /* The segment must not be empty. */
580 if (phdr->p_memsz == 0)
581 return false;
582
583 /* The virtual memory region must both start and end within the
584 user address space range. */
585 if (!is_user_vaddr ((void *) phdr->p_vaddr))
586 return false;
587 if (!is_user_vaddr ((void *) (phdr->p_vaddr + phdr->p_memsz)))
588 return false;
589
590 /* The region cannot "wrap around" across the kernel virtual
591 address space. */
592 if (phdr->p_vaddr + phdr->p_memsz < phdr->p_vaddr)
593 return false;
594
595 /* Disallow mapping page 0.
596 Not only is it a bad idea to map page 0, but if we allowed
597 it then user code that passed a null pointer to system calls
598 could quite likely panic the kernel by way of null pointer
599 assertions in memcpy(), etc. */
600 if (phdr->p_vaddr < PGSIZE)
601 return false;
602
603 /* It's okay. */
604 return true;
605}
#define is_user_vaddr(vaddr)
Definition: vaddr.h:41
Here is the call graph for this function:
Here is the caller graph for this function: