KAIST PintOS ๊ฐ์ ๋ฐ Instruction, ํ์๋ PintOS Slides๋ฅผ ์ฐธ๊ณ ํ๋ฉฐ ํ์ตํ ๋ด์ฉ์ ์ ๋ฆฌํ์์ต๋๋ค.
ํ์ต ๋์ค ์์ฑํ ๋ด์ฉ์ด๋ผ ํ๋ฆฐ ๋ด์ฉ์ด ์์ ์ ์์ต๋๋ค.
Arguments Parsing
Command Line์ ๋ํด ๊ณต๋ฐฑ(' ') ๋จ์๋ก ๋ถ๋ฆฌํด์ผ ํ๋ค. ํ์ฌ๋ Arguments๊ฐ ๋ถํ ๋์ง ์์ ํ๋์ ๋ฐฐ์ด๋ก ์ ๋ ฅ๋๊ณ ์๋ค. ์ด๋ ๊ฒ ์ ๋ ฅ๋๋ฉด, filename์ ์ฐพ์ ์๋ ์๊ฑฐ๋์ ์ฌ๋ฌ ๋ช ๋ น ์ต์ ์ ์ฌ์ฉํ ์๊ฐ ์๋ค. ํํ ์ค์์๋ '๋ฌธ์์ด ๋ถ๋ฆฌ' ํจ์(strtok_r())๋ฅผ ์ง์ํ๋ฏ๋ก ์ด๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
strtok_r()
tid_t
process_create_initd (const char *file_name) {
char *fn_copy;
char *temp_ptr;
char *filename;
tid_t tid;
int size;
filename = strtok_r(file_name, " ", &temp_ptr); // arguments parsing
...
}
์ ํจ์์์ ์ ์ํด์ผ ํ ๊ฒ์ ๊ตฌ๋ถ์(delimiters)๋ก ' '์ด ์๋ " "์ด ๋ค์ด๊ฐ์ผ ํ๋ค๋ ๊ฒ์ด๋ค. ๋ถ๋ฆฌ๋ ๊ฐ ๋จ์ด์ ๋์ ๊ฐํ ๋ฌธ์๊ฐ ํฌํจ๋์ด์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค. ๊ฐํ๋ฌธ์๊ฐ ์์ด์ผ parsing ๋ ๋จ์ด๋ค์ ์ถํ ์ฒ๋ฆฌํ ์ ์๋ค.
/*
Example usage:
char s[] = " String to tokenize. ";
char *token, *save_ptr;
for (token = strtok_r (s, " ", &save_ptr); token != NULL;
token = strtok_r (NULL, " ", &save_ptr))
printf ("'%s'\n", token);
outputs:
'String'
'to'
'tokenize.'
*/
char *
strtok_r (char *s, const char *delimiters, char **save_ptr) {
char *token;
if (s == NULL)
s = *save_ptr;
/* Skip any DELIMITERS at our current position. */
while (strchr (delimiters, *s) != NULL) {
/* strchr() will always return nonnull if we're searching
for a null byte, because every string contains a null
byte (at the end). */
if (*s == '\0') {
*save_ptr = s;
return NULL;
}
s++;
}
/* Skip any non-DELIMITERS up to the end of the string. */
token = s;
while (strchr (delimiters, *s) == NULL)
s++;
if (*s != '\0') {
*s = '\0';
*save_ptr = s + 1;
} else
*save_ptr = s;
return token;
}
์ ํจ์๋ ๋ฌธ์์ด์ ๊ตฌ๋ถ์ ๊ธฐ์ค์ผ๋ก ํ์ฑํ์ฌ token pointer๋ก ์ ๊ทผ ๊ฐ๋ฅํจ์ ์ ์ ์๋ค. token pointer๊ฐ ๋ถ๋ฆฌ๋ ๊ฐ ๋จ์ด ๋ฐฐ์ด์ ์์์ ์ด๋ค.
Arguments Passing
User Process ๊ฐ Initialize๋ ๋, User Stack์ ํ์ํ ์ธ์๊ฐ๋ค์ด Push ๋์ด์ผ ํ๋ค. ํํ ์ค์์๋ Stack ๋ฉ๋ชจ๋ฆฌ๋ฅผ 16์ง์ ํํ๋ก ํ๋ฉด์ ์ถ๋ ฅํ๊ธฐ ์ํด hex_dump() ํจ์๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
stack์ ๊ตฌ์ฑ์ ์์ ๊ฐ์ผ๋ฉฐ ์ด ํํ์ ๋ง๊ฒ ๊ตฌํํ๋ฉด ๋๋ค.
# ์ ๊ทผ
stack top pointer(_if.rsp) ๋ณ์๋ฅผ arguments vector์ ๊ธธ์ด์ ๋ง์ถฐ์ ์ฐ์ฅ์์ผ์ผ ํ๋ค(= Stack ํ์ฅ). ์ฐ์ฅ์ํค๋ฉด์ memcpy ํจ์๋ฅผ ํตํด ์ฐ์ฅํ ์์ญ์ argv[i]๋ฅผ ์ ์ฅํ ์ ์๋ค. ์ด ์์๋๋ก ๊ตฌํํ๋ฉด ์๋์ ๊ฐ๋ค.
for (int i = strlen(argv)-1; i >= 0;i-- ){
_if.rsp = _if.rsp - strlen(argv[i]+1); // ์คํ ํ์ฅ
memcpy(_if.rsp, argv[i], strlen(argv[i])+1); // ํ์ฅํ ๊ณต๊ฐ์ argv ๋ณต์ฌ
argv_ptr[i] = _if.rsp; // rsp ๊ฐ ๊ฐ๋ฆฌํจ argv pointer ์ ์ฅ
}
memcpy()
2๏ธโฃ argv[i] ์ฃผ์์์, 3๏ธโฃ strlen(argv[i])+1 ๊ธธ์ด ๋งํผ, 1๏ธโฃ _if.rsp ์ฃผ์์ ๋ณต์ฌํจ
๐ก ์ธ ๋ฒ์งธ ์ธ์๋ก sizeof(argv[i])๊ฐ ๋ค์ด๊ฐ๋ ๊ฒ ์๋์ ์ฃผ์
์ดํ stack top pinter(_if.rsp)์ ์์น๊ฐ 8์ ๋ฐฐ์(x86-64 ํ๊ฒฝ์ด๋ฏ๋ก)๊ฐ ์๋๋ผ๋ฉด stack top pointer๋ฅผ ํ์ฅํด๋๊ฐ๋ฉฐ 8์ ๋ฐฐ์๊ฐ ๋ ์ ์๋๋ก ํจ๋ฉ ์ฒ๋ฆฌ๋ฅผ ํ๋ค. ํจ๋ฉ์๋ 0์ด ํ ๋น๋๋ค(๊ทธ๋ฆผ์ 0x4747ffe8์ data ๋ถ๋ถ).
User stack์๋ arguments vector์ ์ฒซ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋ argv_ptr ์์ญ๋ ํ์ํ๋ค(์๋ฃ์ argv[i]์ ํด๋น). ์ด๋ ๋ฐ๋ณต๋๋ ํ์์ ์ ์ํด์ผ ํ๋ค(^^.. Debug์์ ํ์ ).
for (int i = temp_cnt-1; i >= 0;i-- ){
_if.rsp = _if.rsp - strlen(argv[i])-1; // ์คํ ํ์ฅ
memcpy(_if.rsp, argv[i], strlen(argv[i])+1); // ํ์ฅํ ๊ณต๊ฐ์ argv ๋ณต์ฌ
argv_ptr[i] = _if.rsp; // rsp ๊ฐ ๊ฐ๋ฆฌํจ argv pointer ์ ์ฅ
}
mod = (KERN_BASE - _if.rsp) % 8; // rsp ์์น์ user stack pointer ์์น ์ฐจ์ด๊ฐ 8์ ๋ฐฐ์์ธ์ง
while(mod != 0){ // 8์ ๋ฐฐ์๊ฐ ์๋๋ผ ๋๋จธ์ง๊ฐ ์๋ค๋ฉด ๋๋จธ์ง ๋งํผ ์คํ ํ์ฅ
_if.rsp --;
*(uint8_t *) _if.rsp = 0;
mod --;
_if.rsp --;
}
์ถ๊ฐ๋ก user stack์ ํํ๋ฅผ ํญ์ ์ผ์ ํ๊ฒ ๋ง์ถ์ด ๋ค๋ฃจ๊ธฐ ์ฉ์ดํ๋๋ก ํ๋ ์์ ์ด ํ์ํ๋ค(Instruction ๊ทธ๋ฆผ ์ฐธ๊ณ ). ๋ํ, ์ฐธ๊ณ stack ๊ทธ๋ฆผ์ argv[0]~[4] ์ฒ๋ผ argv data๋ฅผ ๊ฐ๋ฆฌํค๋ ์ฃผ์๋ฅผ ํ ๋นํด์ผ ํ๋ฏ๋ก ์คํ์ ํ์ฅํ๋ฉฐ argument vector์ ์ฃผ์๋ฅผ ๋ณต์ฌํด์ผํ๋ค. ๋ง์ง๋ง์ผ๋ก Fake Address๋ฅผ ์ํ 8 byte๋ฅผ ํ์ฅํ๋ฉด user stack ํ ๋น์ ๋์ด ๋๋ค.
_if.rsp -= 8; // ํ์ ๋ง์ถ๊ธฐ ์ํ ์๋์ ํจ๋ฉ(8 byte)
memset(_if.rsp, 0, 8);
for (int i = temp_cnt - 1; i >= 0; i--)
{
_if.rsp -= 8; // 8 byte ๋งํผ stack ํ์ฅ
memcpy(_if.rsp, &argv[i], 8); // argument vector์ ์ฃผ์ ๋ณต์ฌ
}
_if.rsp -= 8; // ํ์ ๋ง์ถ๊ธฐ ์ํ Fake Address(8 byte)
memset(_if.rsp, 0, 8);
_if.R.rdi = temp_cnt; // rdi ๋ ์ง์คํฐ์ arguments count ํ ๋น
_if.R.rsi = (char *)_if.rsp + 8; // rsi ๋ ์ง์คํฐ์ fake address๋ฅผ ์ ์ธํ user stack์ ์ฃผ์ ํ ๋น
๐Debug
hex_dump() ํจ์ ์คํ ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ด๊ธด ๋ด์ฉ์ด ์๋ Case
์ด๋๊น์ง parsingํ๊ณ , stack ์ push ํ ๋ด์ฉ์ด ์ ๋ณด์ธ๋ค. ๋ ๊ฐ์ง ๊ฒฝ์ฐ๊ฐ ์์ฌ๋๋ค. ์ฒซ ๋ฒ์งธ๋ hex_dump์์ ์์๋๋ ์ฃผ์๊ฐ stack top pointer๊ฐ ์๋ ๊ฒฝ์ฐ, ๋ ๋ฒ์งธ๋ stack์ ์ push ๋์ง ์์ ๊ฒฝ์ฐ์ด๋ค. ์ฒซ ๋ฒ์งธ case ํ์ธ์ ์ํด hex_dump() ํจ์๋ฅผ ํ์ธํ์๋ค. hex_dump() ํจ์์ ์ธ์๋ก _if.rsp(stack top pointer)๊ฐ ์ ๋ ฅ๋๋๋ฐ, ํจ์ ๋ด์์ _if.rsp ์ฃผ์ ๊น์ง ์ถ๋ ฅํ๊ธฐ ์ํจ์ผ๋ก ํ์ฉ๋์ด ์ด์์ด ์์๋ค. ๋ ๋ฒ์งธ case๋ก ์ธํ ์๋ฌ๋ก ๋ณด์์ผ๋ฉฐ, stack์ pushํ๋ ๋ฐ๋ณต๋ฌธ์์ ํด๊ฒฐํ ์ ์์๋ค.
for (int i = temp_cnt-1; i >= 0;i-- ){
_if.rsp = _if.rsp - strlen(argv[i])-1; // ์คํ ํ์ฅ
memcpy(_if.rsp, argv[i], strlen(argv[i])+1); // ํ์ฅํ ๊ณต๊ฐ์ argv ๋ณต์ฌ
argv_ptr[i] = _if.rsp; // rsp ๊ฐ ๊ฐ๋ฆฌํจ argv pointer ์ ์ฅ
}
๋ฐ๋ณต๋ฌธ์ ๋๋ฉด ๋์๋ก ์คํ์ด ํ์ฅ(_if.rsp ๊ฐ์)๋๋ค. ์ฆ, ๋ฐ๋ณต ํด์ฃผ๋ ํ์๊ฐ ์ค์ํ๋ฐ argv๋ฅผ ๋ณต์ฌํ ๋งํผ๋ง ๋ฐ๋ณตํด์ผํ๋ ๊ฑธ(temp_cnt ํ์) argc -1๋งํผ ๋ฐ๋ณตํ๋ ๊ฒ์ผ๋ก ์ฐฉ๊ฐํ์ฌ ์๋ฌ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด์๋ค ๐ฅฒ ๊ทธ๋๋ ๋ญ ์ ํด๊ฒฐํ๋ค~ ฦช( ห โฃห )ส
+ ์ด์ ์ฝ์ ์ฌ๋ฐ๋ ํ ํฌ ์ํฐํด
ํ๋์ Hello World ํ๋ก๊ทธ๋จ ๋ค์ ์จ๊ฒจ์ง ์ถ์ํ์ ์ธ๊ณ ํํ
'๐งญ KAIST JUNGLE > Pintos' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[PintOS] User Program - System Call2 (Project 2, TIL) (0) | 2024.05.14 |
---|---|
[PintOS] User Program - System Call (Project 2, TIL) (1) | 2024.05.08 |
[PintOS] User Program - ๋ฐฐ๊ฒฝ์ง์(Project 2, TIL) (0) | 2024.05.04 |
[PintOS] Thread - Priority Scheduling (Project 1, WIL) (0) | 2024.05.02 |
[PintOS] Thread - Alarm Clock (Project 1) (0) | 2024.04.29 |