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

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

ํฌ๋ž˜ํ”„ํ†ค ์ •๊ธ€ WEEK08 DAY68 - PintOS Project2 argument passing ๋ณธ๋ฌธ

Krafton jungle

ํฌ๋ž˜ํ”„ํ†ค ์ •๊ธ€ WEEK08 DAY68 - PintOS Project2 argument passing

habbn 2024. 3. 15. 22:31
728x90
๐Ÿ“†2024.3.15

1. argument passing ๊ตฌํ˜„
2. ๋ฐฑ์ค€

 

argument passing ์ธ์ž ์ „๋‹ฌ

 

userํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋˜๊ธฐ ์ „์— ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•œ ์ธ์ž๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.

 

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 ๊ฒฐ๊ณผ

 

 

๋ฐฑ์ค€ 11723 ์ง‘ํ•ฉ

 

์‚ญ์ œํ•˜๊ณ  ์ง€์šฐ๋Š” ๋ถ€๋ถ„์„ ๋‹น์—ฐํ•˜๊ฒŒ append์™€ remove๋กœ ํ–ˆ์—ˆ๋˜.... +empty

์ง‘ํ•ฉ์—์„œ๋Š” add์™€ discard ๊ทธ๋ฆฌ๊ณ  clear ๋ผ๋Š” ์ ์„ ๋ฐฐ์šฐ๊ฒŒ ๋˜์—ˆ๋‹ค.

# 11723 ์ง‘ํ•ฉ
# add x : S์— x ์ถ”๊ฐ€,

import sys
input = sys.stdin.readline

M = int(input())
S = set()
for i in range(M):
    comment = input().split()
    if comment[0] == "add":
        if int(comment[1]) not in S:
            S.add(int(comment[1]))
    elif comment[0] == "remove":
        if int(comment[1]) in S:
            S.discard(int(comment[1]))
    elif comment[0] == "check":
        if int(comment[1]) in S:
            print(1)
        else:
            print(0)
    elif comment[0] == "toggle":
        if int(comment[1]) in S:
            S.discard(int(comment[1]))
        else:
            S.add(int(comment[1]))
    elif comment[0] == "all":
        S = set(range(1, 21))
    elif comment[0] == "empty":
        S.clear()

 

 

728x90