๊ด€๋ฆฌ ๋ฉ”๋‰ด

๋ง๊ฐ๋กœ๊ทธ

ํฌ๋ž˜ํ”„ํ†ค ์ •๊ธ€ WEEK11 DAY 86 - PintOS Project3 - Stack Growth ์™„์„ฑ ๋ณธ๋ฌธ

Krafton jungle

ํฌ๋ž˜ํ”„ํ†ค ์ •๊ธ€ WEEK11 DAY 86 - PintOS Project3 - Stack Growth ์™„์„ฑ

habbn 2024. 4. 1. 22:46
728x90
๐Ÿ“†2024.4.1

1. Stack Growth ์™„์„ฑ
2. ๋ฐฑ์ค€ - ์ˆจ๋ฐ”๊ผญ์งˆ

 

 

Stack Growth ์กฐ๊ฑด

 

1. addr์ด rsp๋ณด๋‹ค ๋†’์€ ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฆฌ์ผœ์•ผ ํ•œ๋‹ค.

2. rsp - 8์— ์ ‘๊ทผํ•œ ๊ฒฝ์šฐ์—๋„ stack growth๋กœ ํ•ด๊ฒฐํ•œ๋‹ค.

3. USER_STACK ์•„๋ž˜์— ์žˆ์–ด์•ผ ํ•˜๊ณ , USER_STACK - (1MB) ์œ„์— ์žˆ์–ด์•ผ ํ•œ๋‹ค. -> USER_STACK ์˜์—ญ ๋‚ด์— ์žˆ์–ด์•ผ ํ•œ๋‹ค.

bool vm_try_handle_fault(struct intr_frame *f UNUSED, void *addr UNUSED,
                         bool user UNUSED, bool write UNUSED, bool not_present UNUSED)
{
    struct supplemental_page_table *spt UNUSED = &thread_current()->spt;
    struct page *page = NULL;
    if (addr == NULL)
        return false;

    if (is_kernel_vaddr(addr))
        return false;

    // true: addr์— ๋งคํ•‘๋œ physical page๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์— ํ•ด๋‹นํ•œ๋‹ค.
    // false: read only page์— writing ์ž‘์—…์„ ํ•˜๋ ค๋Š” ์‹œ๋„์— ํ•ด๋‹นํ•œ๋‹ค.
    if (not_present) // ์ ‘๊ทผํ•œ ๋ฉ”๋ชจ๋ฆฌ์˜ physical page๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ
    {
        /* TODO: Validate the fault */
        // ํŽ˜์ด์ง€ ํดํŠธ๊ฐ€ ์Šคํƒ ํ™•์žฅ์— ๋Œ€ํ•œ ์œ ํšจํ•œ ๊ฒฝ์šฐ์ธ์ง€๋ฅผ ํ™•์ธํ•œ๋‹ค.

        void *rsp = f->rsp; // user access์ธ ๊ฒฝ์šฐ rsp๋Š” ์œ ์ € stack์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
        if (!user)            // kernel access์ธ ๊ฒฝ์šฐ thread์—์„œ rsp๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•œ๋‹ค.
            rsp = thread_current()->stack_rsp;

        // ์Šคํƒ ํ™•์žฅ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ํดํŠธ์ธ ๊ฒฝ์šฐ, vm_stack_growth๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
        if (USER_STACK - (1 << 20) <= rsp - 8 && rsp - 8 <= addr && addr <= USER_STACK)
            vm_stack_growth(addr);

        page = spt_find_page(spt, addr);
        if (page == NULL)
            return false;
        if (write == 1 && page->writable == 0) // write ๋ถˆ๊ฐ€๋Šฅํ•œ ํŽ˜์ด์ง€์— write ์š”์ฒญํ•œ ๊ฒฝ์šฐ
            return false;
        return vm_do_claim_page(page);
    }
    return false;
}

 

stack_bottom์„ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ•˜๋ ค ํ–ˆ์ง€๋งŒ ์–ด๋ ค์›€์„ ๊ฒช๊ณ  ํ…Œ์ŠคํŠธ๊ฐ€ ์™œ ์•ˆ๋˜๋Š”๊ฑฐ์•ผ!!..

 

static void
vm_stack_growth (void *addr UNUSED) {
	vm_alloc_page(VM_ANON|VM_MARKER_0, pg_round_down(addr), true);
}

 

 

1. tests/vm/pt-write-code / tests/vm/pt-write-code2

 

์ด ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผํ•˜๋ ค๋ฉด ์‹œ์Šคํ…œ ์ฝœ read ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ–ˆ๋‹ค.

๊ณ„์†ํ•ด์„œ ์ € ํ…Œ์ŠคํŠธ ๋ถ€๋ถ„์—์„œ fail์ด ๋– ์„œ ๊ณฐ๊ณฐํžˆ ์ƒ๊ฐํ•ด๋ณด๋‹ค ์‹œ์Šคํ…œ ์ฝœ ์ชฝ ๋ฌธ์ œ์ผ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๊ณ  ๋‚˜์˜ ์ƒ๊ฐ์ด ๋งž์•˜๋‹ค๋Š” ์ ์ด ๊ธฐ๋ปค๋‹ค!

 

์ผ๋‹จ ํ˜„์žฌ ์ธ์ž๋กœ ์ฃผ์–ด์ง„ ๋ฒ„ํผ๊ฐ€ spt์— ์žˆ๋Š”์ง€ ํ™•์ธ ํ›„ page๋ฅผ ๋ฐ›์•„์„œ ํ•ด๋‹น page์˜ ์“ฐ๊ธฐ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ณ  ์•„๋‹ˆ๋ผ๋ฉด exit(-1)์„ ํ–ˆ์–ด์•ผ ํ–ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๋‚˜ ๋‚˜์˜ ์Šต๊ด€์ ์ธ ์‹ค์ˆ˜๋กœ page๊ฐ€ ์žˆ๋Š”๋ฐ ์ด ํ•ด๋‹น page๊ฐ€ ์“ฐ๊ธฐ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•ด! ๊ทธ๋Ÿฌ๋ฉด ๋‚˜๊ฐ€! ๋ผ๊ณ  ํ–ˆ์–ด์•ผ ํ–ˆ๋–ค๊ฑธ !page &&!page->writable ๋กœ ๊ฑธ์–ด๋‘ฌ์„œ ์ž๊พธ fail์ด ๋–ด์—ˆ๋˜.. ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค

 

๋™๋ฃŒ ๋ถ„์ด๋ž‘ ์–˜๊ธฐํ•˜๋‹ค ๋ญ”๊ฐ€ ์ž˜๋ชป๋œ ์ ์„ ๊นจ๋‹ซ๊ณ  ๋ฐ”๋กœ ์ˆ˜์ •ํ•ด์ฃผ์—ˆ๋‹ค.

 

๐Ÿค”์˜๋ฌธ์ด์—ˆ๋˜ ์ 

์ฒ˜์Œ์— ์™œ read()์—์„œ ํ˜„์žฌ ํŽ˜์ด์ง€๊ฐ€ ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ์ฒดํฌํ•˜์ง€? write๊ฐ€ ์•„๋‹ˆ๋ผ ์™œ read์—์„œ? ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์—ˆ๋‹ค. 

read๋Š” ํŒŒ์ผ์—์„œ buffer๋กœ๋ถ€ํ„ฐ ์ฝ๋Š”๊ฒƒ(์จ์ฃผ๋Š” ๊ฒƒ) ์ด๊ณ , read , write ๋ชจ๋‘ ์“ฐ๊ธฐํ•œ ํŽ˜์ด์ง€์—ฌ์•ผ ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

๊ทธ๋ž˜์„œ ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•ด์•ผ buffer์— ์“ธ ์ˆ˜ ์žˆ์œผ๋‹ˆ๊นŒ read์—์„œ ์ฒดํฌ๋ฅผ ํ•˜๋Š” ๊ฒƒ!

๋‘˜ ๋‹ค ํ•ด์ค˜๋„ ์ƒ๊ด€ ์—†๋‹ค๊ณ  ํ•œ๋‹ค.

 

int read(int fd, void *buffer, unsigned size) {
	check_address(buffer);
	int byte = 0;
	char *_buffer;
	if (fd == STDIN_FILENO) {
		_buffer = buffer;
		while (byte < size) {
			_buffer[byte++] = input_getc();
		}
	}
	else{
		struct file *_file = get_file_from_fd(fd);
		if (_file == NULL) {
			return -1;
		}
		struct page * _page = spt_find_page(&thread_current()->spt, buffer);
		if(_page && !_page->writable){
			exit(-1);
		}
		lock_acquire(&filesys_lock);
		byte = file_read(_file, buffer, size);
		lock_release(&filesys_lock);
	}
	return byte;
}

 

 

 

2. tests/vm/pt-grow-stk-sc

 

์ด ํ…Œ์ŠคํŠธ๋Š” ๋™์  ๋ณ€์ˆ˜๊ฐ€ ์•„๋‹Œ ์ •์  ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋‘ ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐ™์€์ง€ ์ผ๊ด€์„ฑ์„ ํ™•์ธํ•˜๋Š” ํ…Œ์ŠคํŠธ์˜€๋‹ค. 

๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ๋Š” ๋‹ค ํ†ต๊ณผํ•˜๋Š”๋ฐ ์ด ํ…Œ์ŠคํŠธ๋งŒ ํ†ต๊ณผ๊ฐ€ ์•ˆ๋ผ์„œ printf ๋ฌธ์„ ํ•˜๋‚˜์”ฉ ์ฐ์œผ๋ฉด์„œ ํ™•์ธํ•ด๋ณด๋‹ˆ check_address()์—์„œ ๊ฑธ๋ฆฐ๋‹ค๋Š” ์ ์„ ํ™•์ธํ–ˆ๋‹ค!

 

์ •์  ๋ณ€์ˆ˜๋Š” ๋™์  ๋ณ€์ˆ˜๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— page๊ฐ€ ์—†์œผ๋‹ˆ๊นŒ ๋‹น์—ฐํžˆ spt_find_page() ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฌธ์—์„œ ๊ฑธ๋ ค ์ข…๋ฃŒ๋˜์—ˆ๋˜ ๋ฌธ์ œ์˜€๋‹ค.

๊ทธ๋ž˜์„œ ์ด ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ์ฃผ์„ ์ฒ˜๋ฆฌํ•ด์ฃผ๋‹ˆ ์„ฑ๊ณต!!

	// if(spt_find_page(&thread_current()->spt, (void *)addr) == NULL) {
	// 	exit(-1);
	// }

 

 

stack growth ์ „์ฒด ํ†ต๊ณผ๋กœ ์ด์ œ 33 failed!

 

stack growth ์ƒ๊ฐ๋ณด๋‹ค ๊ฐ„๋‹จํ•˜๊ณ  ์ฝ”๋“œ๋„ ๋งŽ์ด ์ถ”๊ฐ€ ์•ˆํ–ˆ๋Š”๋ฐ ์™œ์ด๋ฆฌ ์‹œ๊ฐ„์„ ์˜ค๋ž˜ ๋ณด๋ƒˆ๋Š”์ง€...ใ…œใ…œ ๊ทธ๋ž˜๋„ ์ดํ•ดํ•˜๊ณ  ๋„˜์–ด๊ฐ”์œผ๋‹ˆ ๋‹คํ–‰์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

 

๋ฐฑ์ค€ ์ˆจ๋ฐ”๊ผญ์งˆ

 

x - 1, x + 1, x*2 ์„ธ ๊ฐ€์ง€์˜ ์กฐ๊ฑด์„ ํ™•์ธํ•˜๋Š” ๊ฒŒ ์–ด๋ ค์› ๋‹ค.

import sys
from collections import deque
input = sys.stdin.readline

def bfs(n):
    q = deque()
    q.append(n)
    
    while q:
        x = q.popleft()
        if x == K:
            print(dist[x])
            break
        for nx in (x-1, x+1, x*2):
            if 0 <= nx <= MAX and not dist[nx]:
                dist[nx] = dist[x] + 1
                q.append(nx)
                
N, K = map(int,input().split())
MAX = 10**5
dist = [0] * (MAX+1)

bfs(N)

 

728x90