์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- ์๊ณ ๋ฆฌ์ฆ
- ์ ์-์ ํฌ
- ์ ๋ํฐ
- User Stack
- C
- TiL
- KRAFTON JUNGLE
- ๋คํธ์ํฌ
- ๋ค์ต์คํธ๋ผ
- ์๊ณ ๋ฆฌ์ฆ์์ -๋๋น์ฐ์ ํ์2
- kraftonjungle
- ํฌ๋ํํค์ ๊ธ
- BFS
- ๋ฐฑ์ค
- ์ถ์ํด๋์ค์์ธํฐํ์ด์ค
- ์ด๋ฒคํธ ํจ์ ์คํ ์์
- ํ์ด์ฌ
- ํฌ๋ํํค ์ ๊ธ 4๊ธฐ
- ํํ ์ค
- 4๊ธฐ
- ์ค๋ธ์
- c#
- ํฌ๋ํํค์ ๊ธ4๊ธฐ
- ํฐ์คํ ๋ฆฌ์ฑ๋ฆฐ์ง
- pintos
- ์ฐ๊ฒฐ๋ฆฌ์คํธ
- Unity
- project3
- anonymous page
- ํฌ๋ํํค ์ ๊ธ
- Today
- Total
๋ง๊ฐ๋ก๊ทธ
PintOS Project2 : User Programs ๋ณธ๋ฌธ
๐ซ PintOS๋ฅผ ์คํ์ํค๊ธฐ ์ํ ์ค๋น ์ค ๋ง์ฃผ์น ์๋ฌ
pintOS ๊ฐ์ ๋จธ์ ์ ํ์ผ์ ๋ฃ๊ธฐ ์ํด์ ๋จผ์ ํ์ผ ์์คํ ํํฐ์ ์ด ์๋ ๋ชจ์ ๋์คํฌ๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค.
pintos-mkdisk filesys.dsk 10
pintos --fs-disk filesys.dsk -p tests/userprog/args-single:args-single -- -q -f run 'args-single onearg'
์์ ์ฝ๋๋ ํ์ผ ์์คํ ํํฐ์ ์ผ๋ก ์ด๋ป๊ฒ ๋์คํฌ๋ฅผ ์์ฑํ๊ณ , ํ์ผ ์์คํ ์ ํ์์ ๋ง๋ค๊ณ , args-single์ด๋ผ๋ ์ด๋ฆ์ ํ๋ก๊ทธ๋จ์ ์ด๋ป๊ฒ ์ ๋์คํฌ์ ๋ง๋ค๊ณ , onearg ๋ผ๋ ์ธ์๋ฅผ ์ ๋ฌํด์ ์คํํ๋์ง์ ๋ํ ์์ฝ ์ฝ๋์ด๋ค.
์ด ์ฝ๋๋ฅผ ์คํํ๊ฒ ๋๋ฉด kernel panic์ ๋ง์ฃผํ๊ฒ ๋๋ค.
Kernel PANIC at ../../threads/vaddr.h:87 in vtop(): assertion
`is_kernel_vaddr (vaddr)' failed.
backtrace ๊ฒฐ๊ณผ
Call stack: 0x800421874b 0x80042072c0 0x800420a92f 0x8004214d12 0x8004209704 0x8004209b22 0x800420762b
Translation of call stack:
0x000000800421874b: debug_panic (lib/kernel/debug.c:32)
0x00000080042072c0: thread_yield (threads/thread.c:340)
0x000000800420a92f: sema_up (threads/synch.c:124)
0x0000008004214d12: interrupt_handler (devices/disk.c:526)
0x0000008004209704: intr_handler (threads/interrupt.c:353)
0x0000008004209b22: intr_entry (threads/intr-stubs.o:?)
0x000000800420762b: kernel_thread (threads/thread.c:456)
์ด ์ค๋ฅ๋ ํ๋ก์ ํธ 1์์ prioirty scheduling์ ์ํด sema_up ํจ์์์ thread_yield ํจ์๋ฅผ ํธ์ถํ ๊ฒ์ด ๋ฌธ์ ์๋ค.
ํ์ผ ์์คํ ์์ sema_up์ ํธ์ถํ ๋ externel interrupt๋ฅผ ๋์ง ์์์ assert๊ฐ ๋ฐ์ํ ๋ฌธ์ ๋ผ๊ณ ํ๋ค.
๊ทธ๋์ thread.c์์ thread_try_yield() ํจ์๋ฅผ ์์ฑํด์ฃผ๊ณ sema_up() ๋ถ๋ถ๋ ์์ ํด์ฃผ๋ฉด ์๋ฌ ํด๊ฒฐ!
/* thread.c */
void thread_try_yield(void){
if(!list_empty(&ready_list) && thread_current() != idle_thread && !(intr_context()))
thread_yield();
}
/* synch.c */
void
sema_up (struct semaphore *sema) {
enum intr_level old_level;
ASSERT (sema != NULL);
old_level = intr_disable ();
if (!list_empty (&sema->waiters))
{
list_sort(&sema->waiters, cmp_priority, NULL);
//sema->waiters์ ์๋ ๋งจ ์ ์ฐ๋ ๋๋ฅผ ๊นจ์ด๋ค.
thread_unblock (list_entry (list_pop_front (&sema->waiters),
struct thread, elem));
}
sema->value++;
intr_set_level (old_level);
//cpu ์๋ณด
thread_try_yield();
}
Argument passing
userํ๋ก๊ทธ๋จ์ด ์คํ๋๊ธฐ ์ ์ ํ๋ก๊ทธ๋จ์ ๋ํ ์ธ์๋ฅผ ์ค์ ํด์ผ ํ๋ค.
es) "/bin/ls -l foo bar" ์ธ์ ์ฒ๋ฆฌํ๊ธฐ
1. ๋ช ๋ น์ด๋ก ๋จ์ด๋ฅผ ๋ถํ ํ๋ค. /bin/ls, -l , foo, bar
2. ๊ฐ ๋ฌธ์์ด์ ์ฃผ์ + ๊ฒฝ๊ณ์กฐ๊ฑด์ ์ํ ๋ํฌ์ธํฐ๋ฅผ ์คํ์ ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ ์์๋ก ํธ์ํ๋ค.
-> argv[0] ์ด ๊ฐ์ฅ ๋ฎ์ ๊ฐ์ ์ฃผ์๋ฅผ ๊ฐ์ง๋ค.
-> ์ต๊ณ ์ ์ฑ๋ฅ์ ์ํด ์ฒซ ๋ฒ์งธ ํธ์ ์ ์ ์คํ ํฌ์ธํฐ๋ฅผ 8์ ๋ฐฐ์๋ก ์ ๋ ฌํ๋ค.
3. %rsi๊ฐ argv ์ฃผ์( argv[0]์ ์ฃผ์)๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ํ๊ณ , %rdi๋ฅผ argc๋ก ์ค์ ํ๋ค.
4. ๋ง์ง๋ง์ผ๋ก ๊ฐ์ง return address๋ฅผ ํธ์ํ๋ค.
-> entry ํจ์๋ ์ ๋ ๋ฐํํ์ง ์์ง๋ง, ํด๋น ์คํ ํ๋ ์์ ๋ค๋ฅธ ์คํ ํ๋ ์๋ค๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ ธ์ผ ํ๋ค.
์คํ ํฌ์ธํฐ๋ 0x4747ffb8๋ก ์ด๊ธฐํ๋๋ค.
Address | Name | Data | Type |
0x4747fffc | argv[3][...] | 'bar\0' | char[4] |
0x4747fff8 | argv[2][...] | 'foo\0' | char[4] |
0x4747fff5 | argv[1][...] | '-l\0' | char[3] |
0x4747ffed | argv[0][...] | '/bin/ls\0' | char[8] |
0x4747ffe8 | word-align | 0 | uint8_t[] |
0x4747ffe0 | argv[4] | 0 | char * |
0x4747ffd8 | argv[3] | 0x4747fffc | char * |
0x4747ffd0 | argv[2] | 0x4747fff8 | char * |
0x4747ffc8 | argv[1] | 0x4747fff5 | char * |
0x4747ffc0 | argv[0] | 0x4747ffed | char * |
0x4747ffb8 | return address | 0 | void (*) () |
RDI: 4 | RSI: 0x4747ffc0
argument passing ์ธ์ ์ ๋ฌ
์ฝ๋์ ํ๋ฆ
init.c → int main(void) → run_actions(argv) → run_task(char **argv) → process_create_initd(task) → thread_create (file_name, PRI_DEFAULT, initd, fn_copy) → initd→process_exec → load, do_iret
1. process_create_initd()
๐๐ป command line์ parsing ํด์ file_name์ ์ฐพ๋๋ค.
- ์ธ์๋ก ๋ค์ด์ค๋ file_name์ด ์คํ ์ ์ ๋ ฅ๋ command line์ด๋ค.
- ์ด command line์ parsingํด์ ํ์ผ ์ด๋ฆ์ ์ฐพ๋๋ค.
- parsingํด์ ์ป์ด๋ธ ํ์ผ ์ด๋ฆ์ด thread_create ํจ์์ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ๋ค์ด๊ฐ์ผ ํ๋ค.
tid_t
process_create_initd (const char *file_name) {
char *fn_copy;
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); //file_name์ ๋ณต์ฌ๋ณธ
if (fn_copy == NULL)
return TID_ERROR;
strlcpy (fn_copy, file_name, PGSIZE);
//Argument Pasing
//command_line์ parsingํด์ file_name ์ฐพ๋๋ค.
char *save_ptr;
strtok_r (file_name, " ", &save_ptr);
//~Argument Pasing
/* Create a new thread to execute FILE_NAME. */
tid = thread_create (file_name, PRI_DEFAULT, initd, fn_copy);
if (tid == TID_ERROR)
palloc_free_page (fn_copy);
return tid;
}
2. process_exec()
๐๐ป ์ธ์๋ก ๋ค์ด์ค๋ f_name์ parsing ํ๊ณ user_stack์ ๋งค๊ฐ๋ณ์๋ค์ push ํ๋ค.
- parsing ํ ์ธ์๋ค์ ๋ด์ parse ๋ฐฐ์ด์ ๊ธธ์ด๋ 64๋ก ์ง์ ํ๋ค.
- strtok_r ํจ์๋ฅผ ํ์ฉํด parsing ํ ๊ฒฐ๊ณผ๋ฅผ count์ parse์ ๋ด์๋๊ณ , ์๋์์ ์๋ก ์ ์ธํ argument_stack ํจ์๋ฅผ ํธ์ถํ ๋ ์ ๋ฌํ๋ค.
- hex_dump() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ๋ค. (๋ฉ๋ชจ๋ฆฌ์ ๋ด์ฉ์ 16์ง์ ํ์์ผ๋ก ์ถ๋ ฅํด ์ค์ ์คํ์ ์ ์ฅ๋ ๊ฐ๋ค์ ํ์ธํ ์ ์๋ค.)
int
process_exec (void *f_name) {
char *file_name = f_name;
bool success;
/* We cannot use the intr_frame in the thread structure.
* This is because when current thread rescheduled,
* it stores the execution information to the member. */
struct intr_frame _if;
_if.ds = _if.es = _if.ss = SEL_UDSEG;
_if.cs = SEL_UCSEG;
_if.eflags = FLAG_IF | FLAG_MBS;
/* We first kill the current context */
process_cleanup ();
// Argument Passing ~
int argc = 0;
char *argv[64]; //parssingํ ์ธ์๋ฅผ ๋ด์ ๋ฐฐ์ด
char *token, *save_ptr;
for (token = strtok_r(file_name, " ", &save_ptr); token != NULL; token = strtok_r(NULL, " ", &save_ptr))
{
argv[argc++] = token;
}
// ~ Argument Passing
/* And then load the binary */
success = load (file_name, &_if);
// Argument Passing ~
argument_stack(argv, argc, &_if); // ํจ์ ๋ด๋ถ์์ argv์ rsp์ ๊ฐ์ ์ง์ ๋ณ๊ฒฝํ๊ธฐ ์ํด ์ฃผ์ ์ ๋ฌ
hex_dump(_if.rsp, _if.rsp, USER_STACK - (uint64_t)_if.rsp, true); // user stack์ 16์ง์๋ก ํ๋ฆฐํธ
// ~ Argument Passing
/* If load failed, quit. */
palloc_free_page (file_name);
if (!success)
return -1;
/* Start switched process. */
do_iret (&_if);
NOT_REACHED ();
}
3. argument_stack()
๐๐ป process_exec() ํจ์์์ parsing ํ ํ๋ก๊ทธ๋จ ๋ฆ๊ณผ ์ธ์๋ฅผ ์คํ์ ์ ์ฅํ๊ธฐ ์ํด ์ฌ์ฉํ ํจ์๋ฅผ ์๋ก ์ ์ธํ๋ค.
1. ํ๋ก๊ทธ๋จ ์ด๋ฆ, ์ธ์ ๋ฌธ์์ด push
์คํ์ ์๋ ๋ฐฉํฅ์ผ๋ก ์ปค์ง๋ฏ๋ก ์คํ์ ์ธ์๋ฅผ ์ถ๊ฐํ ๋ ์ค๋ฅธ์ชฝ-> ์ผ์ชฝ ๋ฐฉํฅ์ผ๋ก push
2. word-align(8์ ๋ฐฐ์)๋ก ๋ง์ถฐ์ฃผ๊ธฐ
๊ฐ ๋ฌธ์์ด์ push ํ๊ณ ๋์ 8byte ๋จ์๋ก ์ ๋ ฌํ๊ธฐ ์ํด padding์ ์ถ๊ฐํ๋ค.
3. ์ธ์ ๋ฌธ์์ด ์ข ๋ฃ๋ฅผ ๋ํ๋ด๋ 0 push
์ ๋ ฌํ๊ณ ๋์ 0์ push ํ๋ค. (์ธ์ ๋ฌธ์์ด๋ค์ ์ข ๋ฃ๋ฅผ ์๋ฏธํ๋ค)
4. ๊ฐ ์ธ์ ๋ฌธ์์ด์ ์ฃผ์ push
์ธ์ ๋ฌธ์์ด push ํ๋ฉด์ argv์ ๋ด์๋ ๊ฐ ๋ฌธ์์ด์ ์ฃผ์๋ฅผ push ํ๋ค.
5. fake return address
๋ค์ ์ธ์คํธ๋ญ์ ์ ์ฃผ์๋ฅผ push ํด์ผ ํ๋๋ฐ, ์ง๊ธ์ ํ๋ก์ธ์ค๋ฅผ ์์ฑํ๋ ๊ฑฐ๋ผ์ ๋ฐํ ์ฃผ์๊ฐ ์๋ค. ๊ทธ๋์ fake return address๋ก 0์ ์ถ๊ฐํ๋ค.
void argument_stack(char **argv, int argc, struct intr_frame *if_)
{
char *arg_address[128];
// ํ๋ก๊ทธ๋จ ์ด๋ฆ, ์ธ์ ๋ฌธ์์ด push
for(int i = argc - 1; i >= 0; i--)
{
int arg_i_len = strlen(argv[i]) +1; //sential(\0) ํฌํจ
if_->rsp -= arg_i_len; //์ธ์ ํฌ๊ธฐ๋งํผ ์คํ์ ๋๋ ค์ค
memcpy(if_->rsp, argv[i], arg_i_len); //๋๋ ค์ค ๊ณต๊ฐ์ ํด๋น ์ธ์๋ฅผ ๋ณต์ฌ
arg_address[i] = (char *)if_->rsp; //arg_address์ ์ ์ธ์๋ฅผ ๋ณต์ฌํด์ค ์ฃผ์๊ฐ์ ์ ์ฅ
}
// word-align(8์ ๋ฐฐ์)๋ก ๋ง์ถฐ์ฃผ๊ธฐ
if(if_->rsp % 8 != 0)
{
int padding = if_->rsp % 8;
if_->rsp -= padding;
memset(if_->rsp, 0, padding);
}
// ์ธ์ ๋ฌธ์์ด ์ข
๋ฃ๋ฅผ ๋ํ๋ด๋ 0 push
if_->rsp -= 8;
memset(if_->rsp, 0, 8);
// ๊ฐ ์ธ์ ๋ฌธ์์ด์ ์ฃผ์ push
for(int i = argc-1; i >= 0; i--)
{
if_->rsp -= 8;
memcpy(if_->rsp, &arg_address[i], 8);
}
// fake return address
if_->rsp -= 8;
memset(if_->rsp, 0, 8);
//rdi ์๋ ์ธ์์ ๊ฐ์, rsi์๋ argv ์ฒซ ์ธ์์ ์์ ์ฃผ์ ์ ์ฅ
if_->R.rdi = argc;
if_->R.rsi = if_->rsp + 8; //fake return address + 8
}
4. process_wait
argument passing ํ ์คํธ๋ฅผ ํ๋ ค๋ฉด ์ผ๋จ wait๋ฅผ ํ๋ด๋ผ๋ ๋ด์ผ ํด์ ์์๋ฐฉํธ์ผ๋ก ๋ฐ๋ณต๋ฌธ์ ์ถ๊ฐํ๋ค.
10์ต์ผ๋ก ํ๋ฉด ๋๋ฌด ๋นจ๋ฆฌ ๋๋๋ฒ๋ฆฌ๊ณ 100์ต์ผ๋ก ํ๋ฉด time out์ด ๋ ์ ์ ๋ค์ด๊ฒ์ํ ๊ฒฐ๊ณผ 30์ต์ผ๋ก ํ๋ ์๋์๋ค.
int
process_wait (tid_t child_tid UNUSED) {
/* XXX: Hint) The pintos exit if process_wait (initd), we recommend you
* XXX: to add infinite loop here before
* XXX: implementing the process_wait. */
for(int i = 0; i < 3000000000; i++);
return -1;
}
Test ๊ฒฐ๊ณผ
User Memory Access
์ปค๋์ ์ข ์ข ์ฌ์ฉ์ ํ๋ก๊ทธ๋จ์ด ์ ๊ณตํ ํฌ์ธํฐ๋ฅผ ํตํด ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํด์ผ ํ๋ค.
๊ทธ๋ฌ๋ ์ฌ์ฉ์๊ฐ ์๋ชป๋ ์ฃผ์ ํฌ์ธํฐ๋ฅผ ์ ๋ฌํ ์ ์์ผ๋ฏ๋ก, ์ปค๋์ ์ด๋ฅผ ๋งค์ฐ ์ ์คํ๊ฒ ์ฒ๋ฆฌํด์ผ ํ๋ค.
-> null ํฌ์ธํฐ,
-> ๋งคํ๋์ง ์์ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
-> ์ปค๋ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ(KERN_BASE ์ด์)
check_address
user ํ๋ก๊ทธ๋จ์ด ์๋ชป๋ ํฌ์ธํฐ๋ฅผ ์ ๋ฌํ๋ฉด exit์ ํธ์ถํ๋ค.
void check_address(void *file_addr)
{
struct thread *t = thread_current();
if(file_addr == "\0" || file_addr == NULL || !is_user_vaddr(file_addr) || pml4_get_page(t->pml4, file_addr) == NULL)
exit(-1);
}
File System
System Calls ์ค์๋ File System๊ณผ ๊ด๋ จ๋ ํธ์ถ์ด ๋ง์๋ฐ, Pintos์์ ์ด๋ฏธ ๊ตฌํ๋์ด ์๋ File System์ ์ ๊ณตํด์ฃผ๊ธฐ ๋๋ฌธ์ filesys.h ๋๋ file.h์์ ์ ์ ํ ํจ์๋ฅผ ์ฐพ์์ ์ฌ์ฉํ๋ฉด ๋๋ค.
File System ์ฝ๋๋ฅผ ์คํํ๋ ๋์์๋ ํ ๋ฒ์ ํ๋์ ํ๋ก์ธ์ค๋ง ์คํ๋๋๋ก ๋๊ธฐํ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
file ๊ด๋ จ๋ ์ฝ๋๊ฐ ์คํ๋๊ธฐ ์ ์ syscall.c์์ ์๋ก ๋ง๋ filesys_lock์ acquireํ ํ์ ์ ๊ทผํ๋๋ก ํด์ผ ํ๋ค.
์ดํ ํ๋ก์ ํธ์์ ๋๊ธฐํ๋ก ์ธํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฏ๋ก lock์ ๊ฑธ์ด์ค์ผ ํ๋ ๋ถ๋ถ์ ์ ๊ฑธ์ด์ค์ผ ํ๋ค..
syscall.h์์ filesys_lock์ ์ ์ญ์ผ๋ก ์๋ก ์ ์ธํ๊ณ syscall_init์์ ์ด๊ธฐํํ๋ค.
/* userprog/syscall.h */
#ifndef USERPROG_SYSCALL_H
#define USERPROG_SYSCALL_H
void syscall_init (void);
struct lock filesys_lock;
#endif /* userprog/syscall.h */
/* userprog/syscall.c */
void syscall_init(void)
{
...
lock_init(&filesys_lock);
}
System Calls ๊ตฌํ
์ ์ ํ๋ก๊ทธ๋จ์ด ์์คํ ์ฝ์ ๋ณด๋ด๋ฉด ์์คํ ์ฝ ํธ๋ค๋ฌ๊ฐ ์์คํ ์ฝ ๋ฒํธ๋ฅผ ๋ฐ์์ค๊ณ , ์ด๋ค ์์คํ ์ฝ ์ธ์๋ค์ ๋ฐ์์ค๊ณ , ๊ทธ์ ์๋ง์ ์ก์ ์ ์ทจํ๋๋ก ๊ตฌํํด์ผ ํ๋ค.
์์คํ ์ฝ ํธ๋ค๋ฌ์ธ syscall_handler()๊ฐ ์ ์ด๊ถ์ ์ป์ผ๋ฉด, ์์คํ ์ฝ ๋ฒํธ๊ฐ %rax์ ์์ผ๋ฉฐ, ์ธ์๊ฐ๋ค์ ์์๋๋ก ์ ๋ฌ๋๋ค. (%rdi, %rsi, %rdx, %r10, %r8 and %r9)
ํธ์ถ์์ ๋ ์ง์คํฐ๋ struct intr_frame์ผ๋ก ์ ๋ฌ๋์ด ์ ๊ทผํ ์ ์๋ค.(struct infr_frame์ ์ปค๋ ์คํ์ ์๋ค.)
์ ์ ํ๋ก๊ทธ๋จ์ ํ๋กํ ํ์ ์ include/lib/user/syscall.h ๋ด๊ฒจ ์๋ค. (์ด๊ณณ์ ํค๋ ํ์ผ๊ณผ ๋ค๋ฅธ include/lib/user์ ์๋ ํ์ผ๋ค์ ์ ์ ํ๋ก๊ทธ๋จ์์๋ง ์ฌ์ฉ๋๋ค.)
-> user/syscall.c ์์ syscall_handler()๋ฅผ ๊ตฌํํด์ ์์คํ ์ฝ ๋ฒํธ, ์ธ์๋ค์ ๋ฐ์์์ ๊ทธ์ ์๋ง์ ์ก์ ์ ์ทจํ๋๋ก ์์คํ ์ฝ ํจ์๋ฅผ ๊ตฌํํด์ผ ํ๋ค.
void
syscall_handler (struct intr_frame *f UNUSED)
{
frame = f;
int sys_num = f->R.rax; //์์คํ
์ฝ ๋ฒํธ
switch(sys_num)
{
case SYS_HALT:
halt();
break;
case SYS_EXIT:
exit(f->R.rdi);
break;
case SYS_FORK:
f->R.rax = fork(f->R.rdi);
break;
case SYS_EXEC:
f->R.rax = exec(f->R.rdi);
break;
case SYS_WAIT:
f->R.rax = wait(f->R.rdi);
break;
case SYS_CREATE:
f->R.rax = create(f->R.rdi, f->R.rsi);
break;
case SYS_OPEN:
f->R.rax = open(f->R.rdi);
break;
case SYS_FILESIZE:
f->R.rax = filesize(f->R.rdi);
break;
case SYS_READ:
f->R.rax = read(f->R.rdi, f->R.rsi, f->R.rdx);
break;
case SYS_WRITE:
f->R.rax = write(f->R.rdi, f->R.rsi, f->R.rdx);
break;
case SYS_SEEK:
seek(f->R.rdi, f->R.rsi);
break;
case SYS_TELL:
f->R.rax = tell(f->R.rdi);
break;
case SYS_CLOSE:
close(f->R.rdi);
break;
default:
break;
}
//printf ("system call!\n");
//thread_exit ();
}
1. halt
src/include/threads/init.h์ ์ ์ธ๋ power_off()๋ฅผ ํธ์ถํ๋ฉด์ ํํ ์ค๋ฅผ ์ข ๋ฃํ๋ค.
-> #include "threads/init.h" ์ถ๊ฐํด์ผ ๋จ
๊ต์ฐฉ ์ํ ๋ฑ์ ๋ํ ์ผ๋ถ ์ ๋ณด๋ฅผ ์๊ฒ ๋๋ฏ๋ก ๊ฑฐ์ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ์ข๋ค.
void halt (void)
{
power_off();
}
2. exit
ํ์ฌ ๋์ ์ค์ธ ์ ์ ํ๋ก๊ทธ๋จ์ ์ข ๋ฃ์ํค๊ณ , ์ปค๋๋ก ์ํ๋ฅผ ๋ฐํํ๋ค.
๋ง์ฝ ํ๋ก์ธ์ค์ ๋ถ๋ชจ๊ฐ wait ์ํ๋ผ๋ฉด , wait์ ๋ค์ด๊ฐ ์ํ๋ฅผ ๋ฐํํ ๊ฒ์ด๋ค.
์ผ๋ฐ์ ์ผ๋ก ์ํ๊ฐ 0์ด๋ฉด ์ฑ๊ณต, 0์ด ์๋ ์๋ ์๋ฌ๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
void exit (int status)
{
struct thread *cur = thread_current();
cur->exit_status = status;
printf("%s: exit(%d)\n", cur->name, status);
thread_exit();
}
3. create
file์ ์ด๋ฆ์ผ๋ก ํ๊ณ ํฌ๊ธฐ๊ฐ inital_size์ธ ์๋ก์ด ํ์ผ์ ์์ฑํ๋ค.
์ฑ๊ณต์ ์ผ๋ก ํ์ผ ์์ฑํ๋ฉด true, ์คํจ false ๋ฐํํ๋ค.
์ฃผ์ด์ง ํฌ์ธํฐ ์ ํจํ ์ฃผ์๊ฐ์ ๊ฐ์ง๋์ง ํ์ธํ๊ธฐ ์ํด check_address() ํจ์๋ฅผ ์์ฑํ์๋ค.
๋ง์ผ ์ ํจํ ์ฃผ์๊ฐ์ด๋ฉด filesys_create()๋ก ํ์ผ ์์ฑํ๋๋ก ํ์๋ค.
bool create (const char *file, unsigned initial_size)
{
check_address(file);
return filesys_create (file, initial_size);
}
4. remove
file์ด๋ผ๋ ํ์ผ์ ์ญ์ ํ๋ค.
bool remove (const char *file)
{
check_address(file);
return filesys_remove(file);
}
5. close()
- ์ด๋ฆฐ ํ์ผ์ ๋ซ๋๋ค.
- ์คํ์ ๋ง์น๊ฑฐ๋ ์ข ๋ฃ๋๋ ํ๋ก์ธ์ค๋ ์๋ฌต์ ์ผ๋ก ์ด ํจ์๋ฅผ ํธ์ถํ์ฌ ์ด๋ฆฐ ํ์ผ ๋์คํฌ๋ฆฝํฐ๋ค์ ๋ซ๋๋ค.
์ด๋ฆฐ ํ์ผ์ ๋ซ์ผ๋ ค๋ฉด ํ์ผ ๋์คํฌ๋ฆฝํฐ์ ํด๋น ํ์ผ์ด ์๋์ง ํ์ธ ํ ํ์ผ ๋์คํฌ๋ฆฝํฐ ํ ์ด๋ธ์์ ์ ๊ฑฐํ๊ณ ํด๋น ํ์ผ์ file_close() ํ์ฌ ๋ซ์์ฃผ๊ณ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํ๋ค.
void close (int fd)
{
struct file_descrpitor *curr_fd = find_file_descriptor(fd);
//ํ์ผ ๋์คํฌ๋ฆฝํฐ๋ฅผ ์ฐพ์ง ๋ชปํ ๊ฒฝ์ฐ ํจ์ ์ข
๋ฃ
if(curr_fd == NULL) return NULL;
//ํ์ผ ๋์คํฌ๋ฆฝํฐ๊ฐ ์ฐ๊ฒฐ๋ ๋ฆฌ์คํธ์์ ํด๋น ํ์ผ ๋์คํฌ๋ฆฝํฐ๋ฅผ ์ ๊ฑฐํ๋ค.
list_remove(&curr_fd->fd_elem);
//ํ์ผ ๋ซ๋๋ค.
file_close(curr_fd->file);
//ํ์ผ๋์คํฌ๋ฆฝํฐ ํด์
free(curr_fd);
}
๊ทธ๋ฆฌ๊ณ ๊ผญ ํค๋ํ์ผ์ ์ถ๊ฐํด์ผํ๋ค!!!! (ํค๋ํ์ผ ์ถ๊ฐ ์ํด์ ๊ณ์ ์๋ฌ๋จ)
#include "filesys/file.h"
#include "filesys/filesys.h"
5-2 . find_file_descriptor
ํ์ผ ๋์คํฌ๋ฆฝํฐ ๋ชฉ๋ก์์ ์ฃผ์ด์ง ํ์ผ ๋์คํฌ๋ฆฝํฐ ๋ฒํธ(fd)๋ฅผ ๊ฐ์ง ํ์ผ ๋์คํฌ๋ฆฝํฐ๋ฅผ ์ฐพ๋ ํจ์๋ฅผ ๋ง๋ค์ด์ค๋ค.
ํ์ฌ ํ์ผ ๋์คํฌ๋ฆฝํฐ์ ๋ฒํธ์ ์ฃผ์ด์ง ํ์ผ ๋์คํฌ๋ฆฝํฐ ๋ฒํธ๋ฅผ ๋น๊ตํ์ฌ ์ผ์นํ๋์ง ํ์ธํ๊ณ ์ผ์นํ๋ค๋ฉด ํด๋น ํ์ผ ๋์คํฌ๋ฆฝํฐ์ ํฌ์ธํฐ๋ฅผ ๋ฐํํ๋ค. ๋ชป ์ฐพ์๋ค๋ฉด NULL์ ๋ฐํํ๊ณ ํจ์๋ฅผ ์ข ๋ฃํ๋ค.
struct file_descrpitor *find_file_descriptor(int fd)
{
struct list *fd_list = &thread_current()->fd_list;
if(list_empty(fd_list)) return NULL;
struct file_descrpitor *file_descriptor;
struct list_elem *cur_fd_elem = list_begin(fd_list);
while(cur_fd_elem != list_end(&fd_list))
{
file_descriptor = list_entry(cur_fd_elem, struct file_descrpitor, fd_elem);
if(file_descriptor->fd_num == fd)
{
return file_descriptor;
}
file_descriptor = list_next(cur_fd_elem);
}
return NULL;
}
๐ฅฒ ํค๋งธ๋ ์
close ๋ถ๋ถ์์ ๋ง์ ์๊ฐ์ด ๊ฑธ๋ ธ๋ค.
์๋ํ๋ฉด ์ฒ์์ find_file_descriptor() ํจ์ ์์ ์ฝ๋๋ค์ close ์์์ ์์ฑํด์ฃผ๋ฉด์ ๋ง์ฝ ํ์ฌ ํ์ผ ๋์คํฌ๋ฆฝํฐ ๋ฒํธ๊ฐ ์ฃผ์ด์ง ํ์ผ ๋์คํฌ๋ฆฝํฐ ๋ฒํธ์ธ์ง ํ์ธํ๋ ์กฐ๊ฑด๋ฌธ ์์์ ์ญ์ ํ๊ณ ํ์ผ ๋ซ๋ ๋ถ๋ถ์ผ๋ก ๊ตฌํ ํ๋๋ฐ ์๊พธ ์๋๋ค. ์๊พธ ์ ์ ํ๋ก๊ทธ๋จ์ด ๋๋์ง ์๋ ์๋ฌ๊ฐ ์๊ฒผ๋๋ฐ ๊ทธ ์ด์ ๊ฐ break๋ฌธ์ ์์ ์ด์ค์....์๋ค.
๊ทธ๋ฆฌ๊ณ open์ ํ๋ฉด์ ํ์ฌ ํ์ผ ํ์ผ ๋์คํฌ๋ฆฝํฐ์ ๋์ ํ ๋น์ ํด์คฌ๋๋ฐ close ๋ถ๋ถ์์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ํด์ ํ๋ ๋ถ๋ถ์ ์์ ์ด๋์ ์ถ๊ฐํด์คฌ๋ค.
6. read
- fd๋ก๋ถํฐ ์ด๋ฆฐ ํ์ผ์ ํฌ๊ธฐ๋ฅผ ์ฝ๊ณ ๋ฒํผ์ ๋ด๋๋ค. ์ค์ ๋ก ์ฝ์ ํ์ผ์ ํฌ๊ธฐ๋ฅผ ๋ฐํํ๋ฉฐ ์คํจ์ -1์ ๋ฐํํ๋ค.
- fd๊ฐ 0์ด๋ฉด input_getc() ๋ฅผ ์ด์ฉํด์ ํค๋ณด๋ ์ ๋ ฅ์ ์ฝ์ด์จ๋ค.
์ฃผ์ด์ง ํ์ผ ๋์คํฌ๋ฆฝํฐ ๋ฒํธ์ ์ผ์นํ๋ ํ์ผ ๋์คํฌ๋ฆฝํฐ๋ฅผ ์ฐพ์ ๊ทธ ํ์ผ์ ์ฝ์ด๋ค์ด๋ฉด๋๋ค.
int read (int fd, void *buffer, unsigned length)
{
check_buffer(buffer);
int byte = 0;
char *ptr = (char *)buffer;
if(fd == 0)
{
for(int i = 0; i < length; i++)
{
*ptr++ = input_getc();
byte ++;
}
}
else
{
lock_acquire(&filesys_lock);
struct file_descriptor *curr_fd = find_file_descriptor(fd);
if(curr_fd == NULL) return -1;
byte = file_read(curr_fd->file, buffer, length);
lock_release(&filesys_lock);
}
return byte;
}
6-2. filesize
์ด๋ ค์๋ ํ์ผ์ ํฌ๊ธฐ๋ฅผ ๋ฐํํ๋ค.(byte ๋จ์๋ก)
int filesize (int fd)
{
struct file_descriptor *curr_fd = find_file_descriptor(fd);
if(curr_fd == NULL) return -1;
return file_length(curr_fd->file);
}
7. write
fd๊ฐ 1(ํ์ค ์ถ๋ ฅ)์ด๋ฉด ์ฝ์์ ์ถ๋ ฅ์ ํด์คฌ๋ค๋ฉด ์ด์ ๋์ด๋ฆฐ ํ์ผ fd๋ก ๋ฒํผ์ ๋ด๊ธด size๋งํผ ์ถ๋ ฅํด์ผ ๋๋ค.
read์ ์๋นํ ์ ์ฌํด์ file_write() ํจ์๋ก ์์ ํด์ฃผ๋ฉด ๋๋ค.
int write (int fd, const void *buffer, unsigned length)
{
check_buffer(buffer);
int byte = 0;
if(fd == 1)
{
putbuf(buffer, length);
byte = length;
}else
{
struct file_descriptor *curr_fd = find_file_descriptor(fd);
if(curr_fd == NULL) return NULL;
lock_acquire(&filesys_lock);
byte = file_write(curr_fd->file, buffer, length);
lock_release(&filesys_lock);
}
return byte;
}
8. open()
file ์ ์ด๊ธฐ ์ํด์๋ ์์คํ ์ฝ open() ํจ์๋ฅผ ๊ตฌํํด์ผ ํ๋ค.
open์ ๊ตฌํํ๊ธฐ ์ํด์๋
1. file์ด ์ ํจํ ์ฃผ์๊ฐ์ธ์ง๋ฅผ ๊ฒ์ฆํด์ผ ํ๋ค.
2. filesys_open๋ฅผ ํธ์ถํด์ ํ์ผ์ openํ๋ค.
3. process_add_file ํจ์๋ฅผ ํธ์ถํด์ ํ์ผ ๋์คํฌ๋ฆฝํฐ ํ ์ด๋ธ์ ํ์ผ์ ์ถ๊ฐํ๊ณ fd๋ฅผ ๋ฐํํ๋ค.
4. ํ์ผ๋์คํฌ๋ฆฝํฐ ํ ์ด๋ธ์ ์ถ๊ฐํ ์ ์๋ ๊ฒฝ์ฐ(fd == -1)์ธ ๊ฒฝ์ฐ์ ํ์ผ์ ๋ซ๊ณ -1์ ๋ฆฌํดํ๋ค.
5. ์คํํ ํ์ผ์ fd๋ฅผ ๋ฐํํ๋ค.
int open (const char *file)
{
check_address(file);
struct file *file_open = filesys_open(file);
if(file_open == NULL)
return -1;
int fd = process_add_file(file_open);
if(fd == -1)
file_close(file_open);
return fd;
}
8-2 process_add_file()
ํ์ฌ ์ค๋ ๋์ ํ์ผ๋์คํฌ๋ฆฝํฐ์ ํ์ฌ ํ์ผ์ ์ถ๊ฐํ๋ค.
ํด๋น ํ์ผ์ ํ์ผ ๋์คํฌ๋ฆฝํฐ ๋ฒํธ๋ฅผ ๋ฐํํ๋ค.
int process_add_file(struct file *file)
{
struct thread *curr = thread_current();
struct file_descriptor *cur_fd = malloc(sizeof(struct file_descriptor));
struct list *fd_list = &thread_current()->fd_list;
cur_fd->file = file;
cur_fd->fd_num = (curr->last_create_fd)++;
list_push_back(fd_list, &cur_fd->fd_elem);
return cur_fd->fd_num;
}
'Krafton jungle > PintOS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
PintOS Project3 : Memory Management (0) | 2024.03.28 |
---|---|
PintOS Project1 : Threads - Alarm Clock , Priority Scheduling (1) | 2024.03.09 |