Pintos P2: Preliminary
3๋ ๊ฐ ์ฐ์ ๊ธฐ๋ฅ์์์ผ๋ก ๋ณต๋ฌด ํ๊ณ , ๋ณตํํด ์ปด๊ณต๊ณผ ์์ ์ ๋ฃ๊ณ ์์ต๋๋ค. ๊ทธ๋์ ๋ง์ด ๋ฐฐ์ ๋ค๊ณ ์๊ฐํ๋๋ฐ, ์ฌ์ ํ ๋ถ์กฑํ ๋ถ๋ถ์ด ๋ง๋ค์ ^^;; ์ญ์ ์ธ์๋ ๋๊ณ ๊ณต๋ถ์ ๊ธธ๋ ๋์ ๊ฒ ๊ฐ์ต๋๋ค.
์ด ๊ธ์ ์ ๊ฐ Pintos P2๋ฅผ ๊ตฌํํ๊ธฐ ์ํด Pintos ์ฝ๋์ ๊ฐ์ข ์๋ฃ๋ฅผ ์ฐพ์๋ณด๋ฉฐ, ์ ๋ฆฌํ ์ฌ์ ์๋ฃ ์ ๋๋ค. Pintos P2 ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ํ ํ์ ์ด๋ผ๊ณ ๋ณด์๋ฉด ๋ ๊ฒ ๊ฐ์ต๋๋ค.
Virtual Memory
์ฌ์ค Virtual Memory๋ Pintos P3์์ ๊ตฌํํ๋ ์ฃผ์ ์ด๋ค. ๊ทธ๋ฐ๋ฐ, ์ค๊ฐ๊ณ ์ฌ ์ค๋นํ ๋๋ถํฐ ์ฉ์ด๊ฐ ํ์ด ๋์์ ์ด์ฉ ์ ์์ด ๋ฏธ๋ฆฌ ๊ณต๋ถ ํ๋ค.
ํ๋น๋ฏธ๋์ด์์ ์ด ์ฃผ์ ์ ๋ํด ์ ์ ๋ฆฌํ ์์์ด ์ฌ๋ผ์ ์์ผ๋ ์ฐธ๊ณ ํ๋๋ก ํ๋ค. ์ฌ๊ธฐ์๋ ์์ฝ๋ง ์ ์ด๋๋ค.
What is Virtual Memory
์ผ๋จ โ๊ฐ์ ๋ฉ๋ชจ๋ฆฌโ๋ผ๋ ๊ธฐ์ ์ ์ค์ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ๋ณด๋ค ํฐ ํ๋ก์ธ์ค๋ฅผ ์คํํ ์ ์๊ฒ ํ๋ ๊ธฐ์ ์ด๋ค.
By
Ehamberg - Own work, CC BY-SA 3.0, Link
๊ตฌํ์ ์ปจ์ ์ ๊ฐ๋จํ๋ฐ, ์คํํ๊ณ ์ ํ๋ ํ๋ก๊ทธ๋จ์ โ์ผ๋ถโ๋ง ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฌํ๊ณ , ์คํํ๋ค. ์ด๊ฒ์ ํ๋ก๊ทธ๋จ์ ์คํํ ๋, ํ๋ก๊ทธ๋จ์ด ์ฌ์ฉํ๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ ์ ์ฒด๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ ค๋ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์์ฃผ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ๋ ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ ค๋๊ณ ์ฌ์ฉํ๋ฉฐ, ์์ฃผ ์ฌ์ฉํ์ง ์๋ ๋ฐ์ดํฐ๋ Disk๋ก ๋ด๋ ค์(swap-out) ์ ์ ๋ณด๊ด ํ๋ค๊ฐ ์ฌ์ฉํ ํ์ด๋ฐ์ด ์ค๋ฉด ๊บผ๋ด์(swap-in) ์ฌ์ฉํ๋ฉด ๋๋ค.
๊ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ 2๊ฐ์ง๊ฐ ์๋๋ฐ, Paging๊ณผ Segmentation์ด๋ค.
Paging
ํ๋ก์ธ์ค์ ๋ ผ๋ฆฌ ์ฃผ์ ๊ณต๊ฐ์ โํ์ด์ง(page)โ๋ผ๋ ๋จ์๋ก ์๋ฅธ๋ค. ์ด๋, ๊ฐ ํ์ด์ง์ ํฌ๊ธฐ๋ ๋ชจ๋ ๋์ผํ๋ค(ex. 4 kb). ๊ทธ๋ฆฌ๊ณ ๋ฌผ๋ฆฌ์ ๋ฉ๋ชจ๋ฆฌ์ ์ฃผ์ ๊ณต๊ฐ์ โํ๋ ์(frame)โ๋ผ๋ ๋จ์๋ก ์๋ฅธ๋ค. ํ๋ ์์ ํ์ด์ง์ ๋์ผํ ํฌ๊ธฐ๋ฅผ ๊ฐ๋๋ค.
ํ๋ก์ธ์์ ๊ฐ ํ์ด์ง๋ ํ๋ก์ธ์ค ๊ด์ ์์ ๋ณด๋ฉด, ์ฐ์ํ ์ฃผ์ ๊ณต๊ฐ์ ์๋๋ผ๋, ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ์ธ ํ๋ ์ ๊ด์ ์์ ๋ณด๋ฉด ๋ถ์ฐ์์ ์ผ๋ก ๋ฐฐ์น ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ํ์ด์ง์ ํ๋ ์์ ๋งคํ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ด โํ์ด์ง ํ ์ด๋ธ(Page Table)โ์ด๋ค.
์ด ํ์ด์ง ํ ์ด๋ธ์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ด ๋ฐ์ํ ๋๋ง๋ค ์ ๊ทผํด์ผ ํ๋ ๋ฐ์ดํฐ๋ก, ์ ๊ทผ์ด ๋งค์ฐ ๋น๋ฒํ๋ค. ๊ทธ๋์ CPU์ ๊ฐ๊น์ด ์บ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ ํด๋๋๋ฐ, ์ด ์บ์ ๋ฉ๋ชจ๋ฆฌ์ ์๋ฃ ๊ตฌ์กฐ๋ฅผ โTLB(Translation Lookaside Buffer)โ๋ผ๊ณ ํ๋ค. ๋ฌผ๋ก , TLB์ Page Table์ ๋ด์ฉ ์ ์ฒด๋ฅผ ๋๊ธฐ ์ด๋ ค์ธ ์ ์๊ณ , ์ด๋ฐ ๊ฒฝ์ฐ โTLB missedโ๊ฐ ๋ฐ์ํ ์๋ ์๋ค.
Segmentation
์ธ๊ทธ๋จผํธ(Segment)๋ ๋ฉ๋ชจ๋ฆฌ์ ํน์ ๊ตฌ์ญ์ ๋ํ๋ธ๋ค. ๊ตฌ์ญ์ด๋ผ๊ณ ํ๋ฉด, Code, Data, Stack ๊ตฌ์ญ์ ๋งํ๋ฉฐ ๊ฐ๊ฐ
- Code Segment (CS)
- Data Segment (DS)
- Stack Segment (SS)
๋ผ๊ณ ํ๋ค. ๊ฐ ์ธ๊ทธ๋จผํธ๋ง๋ค ๋ค๋ฅธ ์ ๊ทผ ๊ถํ์ ๋ถ์ฌํ๋๋ฐ, ์ฝ๋ ์์ญ์ RX๋ง ๊ฐ๋ฅํ๊ณ , Write๋ฅผ ๋ถ๊ฐํ๋ค.
๊ทธ๋ฆฌ๊ณ ํ ํ๋ก์ธ์ค๊ฐ ๋ค๋ฅธ ํ๋ก์ธ์ค์ ๋ฉ๋ชจ๋ฆฌ ์ธ๊ทธ๋จผํธ์ ์ ๊ทผํ์ง ๋ชป ํ๋๋ก ํด์ผ ํ๋ค.
์ธ๊ทธ๋จผํธ์ ํ์ด์ง ๊ธฐ๋ฒ์ ๋น๊ตํ๋ฉด, ์ธ๊ทธ๋จผํธ์ ๊ธฐ๋ณธ ๋จ์์ธ โ์ธ๊ทธ๋จผํธโ๋ ๊ทธ ํฌ๊ธฐ๊ฐ ์ ํด์ง์ง ์๊ณ ๊ฐ๋ณ์ ์ด๋ค. ๊ทธ๋์ ํ ํ๋ก์ธ์ค์ Program Code๋ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ ์์ ํ๋์ ์ธ๊ทธ๋จผํธ์ ๋ชจ๋ ๋ค์ด์์ผ๋ฉฐ ์ฐ์๋ ๊ณต๊ฐ์ ๋ฐฐ์น๋๋ค.
๋ฐ๋ฉด์, ํ์ด์ง์์๋ ์ฝ๋ ์์ญ์ ์ฌ๋ฌ ํ์ด์ง๋ก ๋๋์๊ณ , ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ์์ ๊ฐ ์ฝ๋ ํ๋ ์์ด ์ฐ์์ ์ผ๋ก ์กด์ฌํ์ง ์๋๋ค.
Kernel Memory vs. User Memory
๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํฌ๊ฒ, ์ปค๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ๊ณผ ์ ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ผ๋ก ๋๋๋ค. ๋ ๊ณต๊ฐ์ ์๋ก ์นจ๋ฒํ ์ ์๋ ๊ณต๊ฐ์ด๋ค. ์ปค๋ ๊ณต๊ฐ์๋ ์ปค๋ ๋์์ ํ์ํ code, data, stack, heap ์น์ ์ด ์กด์ฌํ๋ค. ์ ์ ๊ณต๊ฐ์๋ ์ ์ ํ๋ก๊ทธ๋จ์ด ์คํํ๋ code, data, stack, heap์ด ์ ์ฅ๋๋ค. ์ ์ ๊ณต๊ฐ์๋ ์ฌ๋ฌ ํ๋ก๊ทธ๋จ์ด ๊ณต๊ฐ์ ์ ์ ํ ์ ์๋ค.
ํ์ง๋ง ๋ณธ์ธ์ ์ง์ ํ์ธํ์ง ์์ผ๋ฉด ์ฐ์ฐํ๋โฆ ๊ณผ์ฐ์ด ์ด ๋ง์ด ์ง์ง์ธ์ง ๊ถ๊ธํด์ก๋ค ใ
ใ
ใ
์ฐพ์๋ณด๋ vm_stats
๋ผ๋ ๋ช
๋ น์ด๋ฅผ ์ฐ๋ฉด ์ปค๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ผ๋ก ์ผ๋งํผ์ด ์กํ ์๋์ง ํ์ธํ ์ ์๋๋ฐ,
$ vm_stats
Mach Virtual Memory Statistics: (page size of 16384 bytes)
Pages free: 18228.
Pages active: 952019.
Pages inactive: 948651.
Pages speculative: 2472.
Pages throttled: 0.
Pages wired down: 212664.
Pages purgeable: 57595.
...
๋ด๊ฐ ์ฌ์ฉํ๊ณ ์๋ M3 ๋งฅ๋ถ ๊ธฐ์ค์ผ๋ก๋ 212664 * 16384 bytes = 3.48 Gb
์ ๋๊ฐ wired memory, ๊ณ ์ ๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ผ๋ก ์กํ ์๋ค. ์ฐธ๊ณ ๋ก ํ์ฌ ๋งฅ๋ถ์ ์ ์ฒด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ด์ฆ๋ 36 Gb
์ด๋ค. ๊ฐ์ฌํฉ๋๋ค ํ์ฌ๋ ๐ฅฏ ๋์ถฉ 10% ์ ๋๊ฐ ์ปค๋ ๊ณต๊ฐ์ผ๋ก ์กํ ์๋ ์
์ด๋ค.
Interrupt Frame
์ธํฐ๋ฝํธ๊ฐ ๋ฐ์ ํ์ ๋, ํ์ฌ ์์ ์ ๋ฉ์ถ๊ณ ์ธํฐ๋ฝํธ ํธ๋ค๋ฌ๊ฐ ์คํ๋๋ ๋์ CPU์ ์ํ๋ฅผ ์ ์ฅํด๋๊ธฐ ์ํด ์ฌ์ฉํจ.
์ธํฐ๋ฝํธ๊ฐ ๋ฐ์ํ๋ฉด, CPU๋ ํ์ฌ ๋ ์ง์คํฐ์ ์ํ, PC, EFLAS๋ฅผ ๋ชจ๋ ์คํ์ ์ ์ฅํ๋ค. ์คํ์ ์ ์ฅํ ๋, ๊ทธ๋ฅ ์ ์ฅํ๋๊ฒ ์๋๋ผ Interrupt Frame๋ผ๋ ๊ฑฐ์ ๋ด์์ ์ ์ฅํ๋ค.
Stack Frame์ ๋ํด์๋ ์ค๊ฐ๊ณ ์ฌ ๊ณต๋ถํ๋ฉด์ ๋ฐ๋ก ์ ๋ฆฌ๋ฅผ ํด๋๋๋ฐ, Interrupt Frame์ ๊ณต๋ถํ๊ณ ๋๋ ๋๋ค ํ๋ ์์ธ๋ฐ, ์ด๋ค๊ฒ ๋ค๋ฅธ์ง ๊ถ๊ธํด์ก๋ค.
inline assembly
Pintos P2๋ถํฐ๋ C์ฝ๋์์ ์ด์ ๋ธ๋ฆฌ ์ฝ๋๋ ๋ฑ์ฅํ๋ค ใ ใทใท;; ์๋์ ๊ฐ์ด ๋์ค๋๋ฐ, ์ด๋ฒ์ ์ฒ์๋ณด๋ ์ฝ๋๋ผ ํ๋ฒ ์ ๋ฆฌํด๋ณธ๋ค.
asm volatile ("movl %0, %%esp; jmp intr_exit" : : "g" (&if_) : "memory");
์ผ๋จ asm
์ inline assembly๋ฅผ ์ฐ๊ธฐ ์ํ ํค์๋์ด๋ค. asm ("INLINE ASM")
์ผ๋ก ์คํํ ์ ์๋ค.
volatile
์ C์ธ์ ์ต์ ํ ๊ด๋ จ ํค์๋์ด๋ค. ์ปดํ์ผ๋ฌ๊ฐ ์ด ์ฝ๋ ๋ผ์ธ์ ์ต์ ํ ํ์ง ์๋๋ก ๊ฐ์ ํ๋ค. ASM ์ฝ๋๋ฅผ ์ฐ๋ ๊ฒฝ์ฐ, ์ปดํ์ผ๋ฌ๊ฐ ์ต์ ํ๋ฅผ ํตํด ASM ์ฝ๋๋ฅผ ์์ ํ ์ ์๋๋ฐ, ์ด ๊ฒฝ์ฐ ์๋์ ๋ค๋ฅธ ๋์์ ํ๋๋ก ์์ ๋ ์ฐ๋ ค๊ฐ ์๋ค. ์ด๋ฐ ์ปดํ์ผ๋ฌ ์ต์ ํ๋ฅผ ๋นํ์ฑํ ํด์ฃผ๋๊ฒ volatile
ํค์๋๋ผ๊ณ ํ๋ค. volatile
ํค์๋๋ ๊ผญ ASM ์ฝ๋๋ ๊ฐ์ด ์จ์ผ ํ๋ ๊ฑด ์๋๋ค. ์ผ๋ฐ์ ์ธ C ์ฝ๋์์๋ ์ธ ์ ์๋ค.
strtok_r()
/* Breaks a string into tokens separated by DELIMITERS. The
first time this function is called, S should be the string to
tokenize, and in subsequent calls it must be a null pointer.
SAVE_PTR is the address of a `char *' variable used to keep
track of the tokenizer's position. The return value each time
is the next token in the string, or a null pointer if no
tokens remain.
This function treats multiple adjacent delimiters as a single
delimiter. The returned tokens will never be length 0.
DELIMITERS may change from one call to the next within a
single string.
strtok_r() modifies the string S, changing delimiters to null
bytes. Thus, S must be a modifiable string. String literals,
in particular, are *not* modifiable in C, even though for
backward compatibility they are not `const'.
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;
ASSERT (delimiters != NULL);
ASSERT (save_ptr != NULL);
/* If S is nonnull, start from it.
If S is null, start from saved position. */
if (s == NULL)
s = *save_ptr;
ASSERT (s != NULL);
/* 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;
}
์ค์ ์ฝ๋์์ ์ดํด๋ณด์๋ฉด
tid_t
process_execute (const char *file_name) // ์ฌ๊ธฐ
{
char *fn_copy;
/* Make a copy of FILE_NAME.
Otherwise there's a race between the caller and load(). */
fn_copy = palloc_get_page (0);
if (fn_copy == NULL)
return TID_ERROR;
strlcpy (fn_copy, file_name, PGSIZE);
...
}
palloc
โPage allocatorโ์ ์ฝ์๋ก ํด๋น ๊ตฌํ์ src/threads/palloc.c
ํ์ผ์์ ํ์ธํ ์ ์๋ค. ์๋ ๋ด์ฉ์ ํด๋น ํ์ผ์ ์๋ ์ฃผ์์ ๋ด์ฉ์ ํด์.
Page allocator. Hands out memory in page-size (or page-multiple) chunks. See malloc.h for an allocator that hands out smaller chunks.
๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ์ด์ง ํฌ๊ธฐ(๋ณดํต 4kb) ๋๋ ๊ทธ๊ฒ์ ์ ์๋ฐฐ๋ก ํ ๋นํ๋ ๋
์์
๋๋ค. ๋ง์ฝ, ๊ทธ๊ฒ๋ณด๋ค ์ ์ ์ฒญํฌ๋ก ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํด์ผ ํ๋ค๋ฉด, malloc()
์ ์ฐ๋ผ๊ณ ํ๋ค์.
System memory is divided into two โpoolsโ called the kernel and user pools. The user pool is for user (virtual) memory pages, the kernel pool for everything else.
์์คํ ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ปค๋ ํ๊ณผ ์ ์ ํ๋ก ๋๋๋ค๊ณ ํ๋ค. ์ ์ ํ์ ์ ์ ํ๋ก์ธ์ค๊ฐ ์ฐ๋ ์ฉ๋์ด๊ณ , ์ปค๋ ํ์ ์ปค๋์ด ์ฐ๊ธฐ ์ํ ๊ณต๊ฐ์ด๋ค.
The idea here is that the kernel needs to have memory for its own operations even if user processes are swapping like mad.
๋ฉ๋ชจ๋ฆฌ ์ค์(swap)์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํ ์ํฉ์์ ๋ฐ์ํ๋ค. ๋ง์ฝ ์ ์ ํ๋ก์ธ์ค๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ์ผ๋ก ๋ฏธ์น๋ฏ์ด(like mad) ์ค์๋๋ ์ํฉ์ด๋๋ผ๋, ์ปค๋์ด ํ์๋ก ํ๋ ๋ฉ๋ชจ๋ฆฌ๋ ์ปค๋ ํ์์ ํญ์ ํ๋ณด๋๋๋ก ํ๋ค๋ ์๋ฏธ์ด๋ค.
By default, half of system RAM is given to the kernel pool and half to the user pool. That should be huge overkill for the kernel pool, but thatโs just fine for demonstration purposes.
์์คํ ๋ฉ๋ชจ๋ฆฌ์ ์ ๋ฐ์ ์ปค๋ ํ, ๋๋จธ์ง ์ ๋ฐ์ ์ ์ ํ๋ก ๋๋๋ค๋ ๋ง. ๋ฐ๋ชจ ์ฉ๋๋ก๋ ์ด ์ ๋๋ก ์ค์ ํด๋ ์ถฉ๋ถํ๋ค๊ณ ํ๋ค ใ ใ
TODO: ์ด๊ฒ ๋ญ์ง
palloc_get_page()
palloc_free_page()
palloc_get_page()
๋ก ํ ๋น ๋ฐ์ ํ์ด์ง๋ฅผ ํด์ ํด์ฃผ๋ ๋ช
๋ น์ด.
๊ผญ, ํด์ ํด์คํจ!!
TDBโฆ