๊ตฌํ ๋ชฉ๋ก: halt, exit, exec, wait, fork
1. halt()
/* power_off() ํธ์ถํด Pintos ์ข
๋ฃ */
void halt(void)
{
power_off();
}
2. exit()
/* ํ์ฌ ์คํ ์ค์ธ ์ ์ ํ๋ก๊ทธ๋จ ์ข
๋ฃํ๋ ์์คํ
์ฝ */
void exit(int status)
{
/* ์คํ ์ค์ธ ์ค๋ ๋ ๊ฐ์ ธ์ค๊ธฐ */
struct thread *t = thread_current();
/* ํด๋น ์ค๋ ๋์ ์ข
๋ฃ ์ํ ์ ์ฅ */
t->exit_status = status;
/* ์ข
๋ฃ ๋ฉ์ธ์ง ์ถ๋ ฅ ํ ์ค๋ ๋ ์ข
๋ฃ */
printf("%s: exit(%d)\n", t->name, status);
thread_exit();
}
3. exec()
/* ํ์ฌ ํ๋ก์ธ์ค๊ฐ cmd_line์์ ์ด๋ฆ์ด ์ฃผ์ด์ง๋ ์คํ ๊ฐ๋ฅํ ํ๋ก์ธ์ค๋ก ๋ณ๊ฒฝ */
/* ์ด ๋, ์ฃผ์ด์ง ์ธ์ ์ ๋ฌ -> ์ฑ๊ณต ์ ๋ฐํ x, ์คํจ ์ exit state -1 ๋ฐํ ๋ฐ ํ๋ก์ธ์ค ์ข
๋ฃ */
/* ์ด ํจ์๋ ํธ์ถํ ์ค๋ ๋์ ์ด๋ฆ์ ๋ฐ๊พธ์ง ์์ & file descriptor๋ ํธ์ถ ์ ์ด๋ฆฐ ์ํ๋ก ์๋ค */
int exec(const char *file)
{
check_address(file);
/* ์์ ๊ฐ๋ฅํ๋๋ก copyํ๊ธฐ ์ํ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ */
char *file_name = palloc_get_page(PAL_ZERO);
if (file_name == NULL)
{
exit(-1);
}
/* file์ file_name์ผ๋ก ๋ณต์ฌ */
strlcpy(file_name, file, PGSIZE);
/* process_exec ํจ์ ํธ์ถ๋ก ํ์ผ ์คํ */
if (process_exec(file_name) == -1)
{
exit(-1);
}
}
์ ์ธ ๊ฐ ์์คํ ์ฝ์ ๋ณธ๋ ์ํ๋ก๋ ๊ตฌํํ ์ ์์ง๋ง, wait()๊ณผ fork() ์์คํ ์ฝ์ ๊ตฌํํ๊ธฐ ์ํด์ ํ๋ก์ธ์ค ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๋จผ์ ๊ตฌํํด์ผ ํ๋ค.
ํ๋ก์ธ์ค๋ ์คํ ๋์ค ์์คํ ํธ์ถ์ ํตํด ๋ค๋ฅธ ํ๋ก์ธ์ค๋ฅผ ์์ฑํ ์ ์๋ค.
- ๋ถ๋ชจ ํ๋ก์ธ์ค: ์ ํ๋ก์ธ์ค๋ฅผ ์์ฑํ ํ๋ก์ธ์ค
- ์์ ํ๋ก์ธ์ค: ๋ถ๋ชจ ํ๋ก์ธ์ค์ ์ํด ์์ฑ๋ ํ๋ก์ธ์ค
๋ฌผ๋ก ์์ ํ๋ก์ธ์ค๋ ๋ ๋ค๋ฅธ ํ๋ก์ธ์ค๋ฅผ ์์ฑํ ์ ์๋ค. ์ด๋ ๊ฒ ์์ฑ๋ ์ด๋ค์ด ๋ ๋ค๋ฅธ ์ ๋ค์ ๋ณ๋ ํ์์ผ๋ก ์ฌ๋ฌ ํ๋ก์ธ์ค๊ฐ ๋์ ์คํ๋๋ค. (์ฝ๊ฐ ํธ๋ฆฌ ๊ตฌ์กฐ)
ํ์ฌ PintOS์๋ ๋ถ๋ชจ/์์ ํ๋ก์ธ์ค๋ฅผ ๋ช
์ํด์ฃผ๋ ์ ๋ณด๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋ถ๋ชจ/์์์ ๊ตฌ๋ถ์ด ์๊ณ ,
๋ถ๋ชจ๊ฐ ์์ ํ๋ก์ธ์ค์ ์ ๋ณด๋ฅผ ์์ง ๋ชป ํด ์์ ํ๋ก์ธ์ค๊ฐ ์์/์ข
๋ฃ๋๊ธฐ ์ ์ ๋ถ๋ชจ ํ๋ก์ธ์ค๊ฐ ์ข
๋ฃ๋์ด๋ฒ๋ฆฌ๋ ํ์์ด ๋ฐ์ํ๋ค. ์ฆ, ์ด๋ ํ๋ก๊ทธ๋จ์ด ์คํ๋์ง ์๋๋ค๋ ์๋ฏธ๋ค.
์ด๋ฅผ ๊ณ ์น๊ธฐ ์ํด ์ฐ๋ฆฌ๋ ํ๋ก์ธ์ค ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๋์ ํ๊ณ , ์ธ๋งํฌ์ด๋ฅผ ํ์ฉํด ์์ ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ๋ ๋ ๋ถ๋ชจ ํ๋ก์ธ์ค์๊ฒ ์๊ทธ๋์ ์ฃผ๊ณ ์ข ๋ฃํ๊ฒ ๋ ์ ์๋๋ก ์์ ํด์ผ ํ๋ค. (๋ถ๋ชจ๊ฐ ์์์ ๊ธฐ๋ค๋ฆฌ๊ณ ์ข ๋ฃ๋ ์ ์๋๋ก)
/* Project(2) */
struct intr_frame parent_if; /* ๋ถ๋ชจ ํ๋ก์ธ์ค์ ์ธํฐ๋ฝํธ ํ๋ ์ */
struct list child_list; /* ์์ ๋ฆฌ์คํธ */
struct list_elem child_elem;
struct file *running_f; /* ์คํ ์ค์ธ ํ์ผ */
int exit_status; /* ์ข
๋ฃ ์ํ */
struct semaphore exit_sema; /* ์์ ํ๋ก์ธ์ค exit ๋๊ธฐ ์ธ๋งํฌ์ด */
struct semaphore wait_sema; /* ์์ ํ๋ก์ธ์ค ์ข
๋ฃ ๋๊ธฐ ์ธ๋งํฌ์ด */
struct semaphore fork_sema; /* ์์์ load ์๋ฃ ๋๊ธฐ ์ธ๋งํฌ์ด */
/* thread.c/init_thread() */
list_init(&t->child_list);
t->exit_status = 0;
/* thread.c/thread_create() */
sema_init(&t->exit_sema, 0);
sema_init(&t->load_sema, 0);
sema_init(&t->wait_sema, 0);
sema_init(&t->fork_sema, 0);
list_push_back(&thread_current()->child_list, &t->child_elem);
/* Project(2) Process hierarchy */
struct thread *get_child_process(int pid)
{
/* ์์ ๋ฆฌ์คํธ์ ์ ๊ทผํ์ฌ ํ๋ก์ธ์ค ๋์คํฌ๋ฆฝํฐ ๊ฒ์ */
/* ํด๋น pid๊ฐ ์กด์ฌํ๋ฉด ํ๋ก์ธ์ค ๋์คํฌ๋ฆฝํฐ ๋ฐํ */
/* ๋ฆฌ์คํธ์ ์กด์ฌํ์ง ์์ผ๋ฉด NULL ๋ฆฌํด */
struct thread *t = thread_current();
struct list_elem *e = list_begin(&t->child_list);
for (e; e != list_end(&t->child_list); e = list_next(e))
{
struct thread *t = list_entry(e, struct thread, child_elem);
if (t->tid == pid)
return t;
}
return NULL;
}
์ด์ wait()๊ณผ fork() ์์คํ ์ฝ์ ๊ตฌํํด๋ณด์.
4. wait()
int wait(pid_t pid)
{
return process_wait(pid);
}
์์คํ ์ฝ ์์ฒด๋ ๋ณ ๊ฒ ์๋ค. process_wait()๋ง์ ํธ์ถํ๋ค. ๊ทธ๋ผ process_wait()์ ํ๊ณ ๋ค์ด๊ฐ๋ณด์.
์์์ ๋งํ๋ ๊ฒ์ฒ๋ผ ๋ถ๋ชจ ํ๋ก์ธ์ค๋ ์์ ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ๋๊ธธ ๊ธฐ๋ค๋ ค์ผ ํ๋ค. ์ด๋ฅผ ์๊ฐํ๊ณ process_wait()์ ์ฌ๋ฐ๋ฅด๊ฒ ์์ฑํ๋ค.
/* ์์ ํ๋ก์ธ์ค๊ฐ ์ข
๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ณ , ์ข
๋ฃ ์ํ ๋ฐํ */
int process_wait(tid_t child_tid UNUSED)
{
/* ์์ ํ๋ก์ธ์ค ๋ฐ์์ค๊ธฐ */
struct thread *child = get_child_process(child_tid);
if (child == NULL)
{
return -1;
}
/* ์์ ํ๋ก์ธ์ค๊ฐ ์ข
๋ฃ๋ ๋๊น์ง ๋๊ธฐ = ํด๋น ํ๋ก์ธ์ค๊ฐ ์ข
๋ฃ๋ ๋ sema_up */
sema_down(&child->wait_sema);
/* ์์ ํ๋ก์ธ์ค๊ฐ ์ข
๋ฃ๋์์ผ๋ฉด ์์ ๋ฆฌ์คํธ์์ ํด๋น ์์ ์ญ์ */
list_remove(&child->child_elem);
/* ์์์ ๋๊ธฐ ์ํ ์ดํ */
sema_up(&child->exit_sema);
return child->exit_status;
}
๊ทธ๋ฐ๋ฐ wait() ๊ตฌํ์ ์ํด ์๊ฐํ๋ค ๋ณด๋ฉด, process_exit()๊ณผ ์ฐ๊ด์ด ์์ ๊ฑฐ๋ผ๋ ๊ฑธ ์ ์ ์๋ค.
๊ทธ๋ผ process_exit()์๋ ๊ด๋ จ ๋ด์ฉ์ ์์ฑํด์ฃผ์.
void process_exit(void)
{
struct thread *curr = thread_current();
/* ํด๋น ํ๋ก์ธ์ค์ fdt์ ๋ชจ๋ ๊ฐ์ 0์ผ๋ก ๋ง๋ค์ด์ค, ์ฆ ๋ชจ๋ ์ด๋ฆฐ ํ์ผ ๋ซ๊ธฐ */
for (int i = 0; i < FDTCOUNT_LIMIT; i++)
{
close(i);
}
/* fd table ๋ฉ๋ชจ๋ฆฌ ํด์ */
palloc_free_multiple(curr->fdt, FDT_PAGES);
/* ์คํ ์ค์ธ ํ์ผ ๋ซ๊ธฐ */
file_close(curr->running_f);
process_cleanup();
/* ์์ ์ข
๋ฃ๋ฅผ ๋๊ธฐํ๋ ๋ถ๋ชจ ํ๋ก์ธ์ค๋ฅผ ๋๊ธฐ ์ํ์์ ์ดํ๋๋๋ก */
sema_up(&curr->wait_sema);
/* ๋ถ๋ชจ ํ๋ก์ธ์ค๊ฐ ์์์ ๋ฆฌ์คํธ์์ ์ง์ธ ์ ์๋๋ก ๋๊ธฐ */
sema_down(&curr->exit_sema);
}
sema๊ฐ ๋ง์ด ํท๊ฐ๋ ธ๋๋ฐ, ๋ํผ์ ์ด๊ธด ํ์ง๋ง ์ ๋ฆฌ๋ฅผ ํ์๋ฉด
- process_wait
๋ถ๋ชจ๊ฐ ์์์ด ์ข ๋ฃ๋๊ธธ ๊ธฐ๋ค๋ฆฌ๊ธฐ ์ํด sema_down(wait_sema)๋ก ์ ์ ๋ฌ- process_exit
์์์ ์ํ์ด ๋๋๋ฉด process_exit์์ ๋ถ๋ชจ์๊ฒ sema_up(wait_sema)๋ก ์ข ๋ฃ๋ฅผ ์๋ ค ๋ถ๋ชจ์ ๋๊ธฐ ์ํ๋ฅผ ํ๊ณ , ๋ถ๋ชจ๊ฐ ๋๋ฅผ ์ง์ธ ์ ์๋๋ก sema_down(exit_sema)๋ก ๊ธฐ๋ค๋ฆผ- process_wait
๋ถ๋ชจ๋ ์์์ด ์ข ๋ฃ๋์์ผ๋ ๋๊ธฐ์์ ํ๋ ค, ํด๋น ์์์ ์์ ๋ฆฌ์คํธ์์ ์ง์ฐ๊ณ , ์ง์ฐ๊ธธ ๊ธฐ๋ค๋ฆฌ๋ ์์์๊ฒ sema_up(exit_sema)๋ก ๋๊ธฐ ์ํ๋ฅผ ํ์ด์ค
์ด๋ ๊ฒ ํ๋ฉด wait() ๊ตฌํ๋ ๋์ด ๋๋ค.
๋ง์ง๋ง fork()๋ฅผ ๊ตฌํํด๋ณด์.
5. fork()
/* ํ์ฌ ํ๋ก์ธ์ค์ ๋ณต์ ๋ณธ์ธ ์ ํ๋ก์ธ์ค ์์ฑ */
pid_t fork(const char *thread_name, struct intr_frame *f)
{
check_address(thread_name);
return process_fork(thread_name, f);
}
fork๋ ์์คํ
์ฝ ์์ฒด๋ ๋ณ ๊ฒ ์๋ค.
์ธ์๊ฐ ํฌ์ธํฐ์ด๊ธฐ ๋๋ฌธ์ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํ ํ process_fork()์ ํธ์ถํ๋ค.
/ ํ์ฌ ํ๋ก์ธ์ค๋ฅผ ๋ณต์ ํด ์ ํ๋ก์ธ์ค๋ฅผ ์์ฑ /
tid_t process_fork(const char *name, struct intr_frame *if_ UNUSED)
{
struct thread *t = thread_current();
memcpy(&t->parent_if, if_, sizeof(struct intr_frame));
/* ์ธ์๋ก ๋ฐ์ name์ผ๋ก ๋ ์ ์ค๋ ๋ ์์ฑ */
tid_t pid = thread_create(name, PRI_DEFAULT, __do_fork, t);
if (pid == TID_ERROR)
{
return TID_ERROR;
}
/* ๋ถ๋ชจ ํ๋ก์ธ์ค์ ์์ ๋ฆฌ์คํธ์์ ๋ฐฉ๊ธ ์๋ก ์์ฑ๋ ์์ ํ๋ก์ธ์ค ๊ฐ์ ธ์ค๊ธฐ */
struct thread *child = get_child_process(pid);
/* ์์ ํ๋ก์ธ์ค์ __do_fork๋ฅผ ๋๊ธฐ */
/* __do_fork์์ ๋ณต์ ๊ฐ ์๋ฃ๋๋ฉด sema_up์ ํด์ค์ผ๋ก์จ ๋๊ธฐ ์ดํ๋๋ฉฐ ์ข
๋ฃ */
sema_down(&child->fork_sema);
return pid;
}
๋งจ ์ฒ์์ ๊ตณ์ด ์คํ ์ค์ธ ๋ถ๋ชจ ํ๋ก์ธ์ค์ contexts๋ฅผ ๋ณต์ฌํ๋ ์ด์ ๋ if ์ ๋ณด๋ฅผ ์ง์ ๋๊ธธ ์, ๋ถ๋ชจ ํ๋ก์ธ์ค๊ฐ ๊ณ์ ์คํํ๋ฉฐ ๊ฐ์ด ๋ณํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋๋ฌธ์ ๋ถ๋ชจ ํ๋ก์ธ์ค์ parent_if์ if๊ฐ์ ๋ณต์ฌํ ํ, ๋ถ๋ชจ ํ๋ก์ธ์ค๋ฅผ __do_fork์ ์ธ์๋ก ๋ด์์ค๋ค.
์ด๋ ๊ฒ ๋ชจ๋ ์์คํ ์ฝ์ ๊ตฌํ์ด ๋๋ฌ๋ค. ๋๋ ์ด 95๊ฐ์ Test-case ์ค 94๊ฐ๋ฅผ pass ํ๋๋ฐ, ๋ง์ง๋ง๊น์ง multi-oom์ ํต๊ณผํ์ง ๋ชป ํ๋ค. ํด๋น ์ผ์ด์ค๋ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๊ฒ์ฌํ๋ค๊ณ ํ๋ ๊ฒ ๊ฐ์๋ฐ.. ๋์ ํ ์ด๋ ๋ถ๋ถ์ธ ์ง ๋ชจ๋ฅด๊ฒ ๋ค. ์ฝ๋๋ฅผ ์์ฑํ๋ ์ค๊ฐ์ค๊ฐ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ์ ํด์ผ๊ฒ ๋ค.
๋ง์ง๋ง์ผ๋ก ํ ์คํธ ์ผ์ด์ค๋ค ๊ทธ๋ฅ ์ ๋๋ฉด ์ด๋ป๊ฒ๋ ํต๊ณผํ๊ฒ ๋ง๋ค๊ธฐ ์ํด ๋ง๊ณ ๋ผ๋ก ์ณ๋ด๋๋ด... ์ฌ์ค ๊ธฐ์ต์ด ์ ์ ๋์ง๋ง, ๊ธฐ์ต๋๋ ํธ๋ฌ๋ธ ์ํ ๋ช ๊ฐ ์์ฑํ๊ณ ๋ง๋ฌด๋ฆฌํ๊ฒ ๋ค.
[ํธ๋ฌ๋ธ ์ํ ]
- fork๊ฐ ์ ๋๋ ๋ฌธ์
: duplicate_pte์์ ์ฒซ ๋ฒ์งธ ์กฐ๊ฑด๋ฌธ parent_page๊ฐ kernel_page์ธ ๊ฒฝ์ฐ ์ฆ์ ๋ฐํํ๋ผ๊ณ ๋์ด ์์ด์ false์ธ ์ค ์์๋๋ฐ, true๋ก ํด์ค์ผ ํ์- rox ๊ด๋ จ TC๋ค์ด ํต๊ณผ๋์ง ์์๋ ๋ฌธ์
: process_exit์์ running file์ file_close ํด์ผ ํจ & load์ done์์ file_close(file)๋ฅผ ์ง์์ผ ํจ
-> ์ฆ, load์์ ์คํํ๊ณ done์์ ํ์ผ ๋ซ์๋ฒ๋ฆฌ๊ณ ์์์์- ๋ช ๊ฐ ํ ์คํธ๊ฐ ํต๊ณผ๋์ง ์์๋ ๊ฑด
: wait_sema๋ฅผ ์ ์ฉํ์ง ์์์ด์- ๋ง์ง๋ง์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ํด์ ์ lock&sema ๊ด๋ฆฌ ์ ํ๊ธฐ ์ค์ -> multi-oom test-case๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋์ ๊ด๋ฆฌ ์๊ตฌ
์ด๊ฑด ํธ๋ฌ๋ธ ์ํ
์ ์๋๋ฐ, ๋๋ฒ๊น
์ ์ ๋ง ์ ํ์ฉํด์ผ๊ฒ ๋ค๊ณ ๋ค์ ํ ๋ฒ ๋๊ผ๋ค.
๋๋ ๋ชจ๋ฅด๊ฒ ์๊พธ ๋๋ฒ๊น
์ ํ์ฉํ์ง ์๊ฒ ๋๋ ๊ฒ ๊ฐ๋ค.
printf()๋ ๋ญ๋ ๋๋ฒ๊น
์ ํ๋ค๋ณด๋ฉด ์์คํ
์ด ์ด๋ป๊ฒ ํ๋ฌ๊ฐ๋์ง ํ์
ํ ์ ์๋ค.
์ค๋ฅ๊ฐ ๋ฌ์ ๋๋ TC๊ฐ fail์ด ๋ด์ ๋ ๋ฟ๋ง ์๋๋๋ผ๋ ํจ์ ํ๋ฆ์ด ์ด๋ป๊ฒ ๋๋ ์ง ์๊ณ ์ถ์ ๋์๋ ํฐ ์์ฉ์ ํ๋ค.