(cํ์ผ์ userprog, hํ์ผ์ include/userprog ์ ์๋ค)
๐ uerpog/
: user program loader์ ์์ค์ฝ๋
process.c
,ย process.h
: ELF ๋ฐ์ด๋๋ฆฌ(=ELF ์คํํ์ผ)๋ค์ ๋ก๋ํ๊ณ ํ๋ก์ธ์ค๋ฅผ ์คํ
syscall.c
,ย syscall.h
: part2์์ ์์คํ
์ฝ์ด ํ์๋ก ํ๋ ๋ค๋ฅธ ์ผ์ ์ํํ๋ ์ฝ๋๋ฅผ ์ํ
exception.c
,ย exception.h
: ์์ธ์ฌํญ ์ฒ๋ฆฌ (page_fault()
์์ )
gdt.c
,ย gdt.h
: x86-64๋ segmented ์ํคํ
์ณ
tss.c
,ย tss.h
: Task-State Segment (TSS)๋ x86 ์ํคํ
์ณ์ ๋ฌธ๋งฅ๊ตํ์ ์ฌ์ฉ๋ฉ๋๋ค. ํ์ง๋ง x86-64์์ ๋ฌธ๋งฅ๊ตํ(context switching = task switching)์ ์ง์์ด ์ค๋จ๋ ๊ธฐ๋ฅ์
๋๋ค. ๊ทธ๋๋ TSS๋ ์ฌ์ ํ ring switching ๋์ ์คํ ํฌ์ธํฐ๋ฅผ ์ฐพ์๋ด๊ธฐ ์ํด ์ฌ์ฉ๋๊ณ ์์ต๋๋ค.
๐ filesys/
: ๊ธฐ๋ณธ์ ์ธ file system์ ์์ค์ฝ๋
๐lib/
: ํ์ค C ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ผ๋ถ๋ถ์ด ๊ตฌํ๋์ด์์
๐ include/lib/kernel/
: Pintos ์ปค๋์๋ง ํฌํจ๋ C ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ผ๋ถ
#include <...>
ํ๊ธฐ๋ฒ ์ฌ์ฉ๐ include/lib/user/
: Pintos user programs ์์๋ง ์ฌ์ฉ๋๋ C ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ผ๋ถ
#include <...>
ํ๊ธฐ๋ฒ์ผ๋ก ํฌํจ๐ examples/
: project 2 ์์ ์ฌ์ฉํ user programs ์ฉ ์์ ๋ค
๐ Makefile
: pinots/src/Makefile.build ์ ๋ณต์ฌ๋ณธ์ผ๋ก, kernel์ ๋น๋ํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช
๐ kernel.o
: ์ปค๋ ์ ์ฒด์ ์ํ Object file
๐ kernel.bin
: ์ปค๋์ ๋ฉ๋ชจ๋ฆฌ ์ด๋ฏธ์ง
๐ loarder.bin
: kernel loader์ ๋ฉ๋ชจ๋ฆฌ ์ด๋ฏธ์ง
build
์ ํ์ ๋๋ ํ ๋ฆฌ๋ค์ ์ปดํ์ผ๋ฌ๊ฐ ๋ง๋ object ํ์ผ๋ค(.o
)๊ณผ dependency ํ์ผ๋ค(.d
)์ ํฌํจuserprog/build
์ ์๋ pintos-mkdisk filesys.dsk 2
์คํpintos --fs-disk filesys.dsk
: ์ด๋ค disk ์ธ์ง ์ง์ pintos SCRIPT_COMMANDS -- -f -q
: ํ์ผ ์์คํ
ํํฐ์
ํฌ๋งทํ
-p
(put, ์ ์ฅ)์ -g
(get, ๊ฐ์ ธ์ค๊ธฐ) ์ต์
:ํ์ผ๋ช
์ถ๊ฐuserprog/build
๋ผ๊ณ ๊ฐ์ ํ์ ์ฐ์ธ ์ฝ๋)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
์ด๋ผ๋ ์ด๋ฆ์ ํ๋ก๊ทธ๋จ(Project2 ์ 2๋ฒ test)๋ฅผ ์ด๋ป๊ฒ ์ ๋์คํฌ์ ๋ง๋ค๊ณ ,onearg
๋ผ๋ ์ธ์๋ฅผ ์ ๋ฌํด์ ์คํํ๋์ง์ ๋ํ ์์ฝ ์ฝ๋pintos --fs-disk=10 -p tests/userprog/args-single:args-single -- -q -f run 'args-single onearg'
--filesys-size=n
ย ์ต์
: pintos ์คํ ๋์ ๋๋ต n
MB ์ ์์ ํ์ผ ์์คํ
ํํฐ์
์์ฑx86-64 ELF ์คํํ์ผ๋ค์ ๋ง๋ค์ด๋ด๋ ์์์ ์ปดํ์ผ๋ฌ์ ๋ง์ปค๋ฅผ ์ฌ์ฉํด Pintos๋ฅผ ์ํ ํ๋ก๊ทธ๋จ์ ๋ง๋ค๊ธฐ (์ปดํ์ผ๋ฌ์ ๋ง์ปค์ ์ ๊ณต)
๋ณต์ฌํด์ ๋ฎ์ด์ธ ์ ์๋ ํด๋ฆฐํ ๋ ํผ๋ฐ์ค ํ์ผ ์์คํ ๋์คํฌ๋ฅผ ๋ง๋ค์ด๋๊ธฐ
USER_STACK +----------------------------------+
| user stack |
| | |
| | |
| V |
| grows downward |
| |
| |
| grows upward |
| ^ |
| | HEAP |
| | |
+----------------------------------+
| uninitialized data segment (BSS) |
+----------------------------------+
| initialized data segment |
+----------------------------------+
| code segment |
0x400000 +----------------------------------+ KERN_BASE
| |
| |
| |
| |
0 +----------------------------------+
+ ํ ์คํํ์ผ์ ๋ ์ด์์์ ๋ณด๊ธฐ ์ํด์๋ -p
์ต์
๊ณผ ํจ๊ป objdump
๋ช
๋ น์ด ์คํ
์ปค๋(์์คํ ์ฝ)์ ์ ์ ํ๋ก๊ทธ๋จ์ด ์ ๊ณตํ ํฌ์ธํฐ๋ค์ ํตํด ๋ฉ๋ชจ๋ฆฌ์ ์์ฃผ ์ ๊ทผํจ
์ ์ ๊ฐ ์๋ชป๋ ํฌ์ธํฐ๋ฅผ ์ปค๋์ ์ ๋ฌํ ์ ์์
์๋ชป๋ ํฌ์ธํฐ๋ค์ ์ปค๋๊ณผ ๋ค๋ฅธ running ํ๋ก์ธ์ค๋ค์๊ฒ ์
์ํฅ์ ๋ฏธ์น์ง ์๊ณ ๊ฑฐ๋ถ๋์ด์ ธ์ผ ํ๋ฏ๋ก,
๋ฌธ์ ๊ฐ ๋๋ ํ๋ก์ธ์ค๋ฅผ ์ข
๋ฃ ์ํค๊ณ ๊ทธ ํ๋ก์ธ์ค์ ์์๋ค์ ํด์ ํด์ผ ํฉ๋๋ค.
์ ์ ๊ฐ ์ ๋ฌํ ์๋ชป๋ ํฌ์ธํฐ์ ๋ํ ๋์
static int64_t
get_user (const uint8_t *uaddr) {
int64_t result;
__asm __volatile (
"movabsq $done_get, %0\n"
"movzbq %1, %0\n"
"done_get:\n"
: "=&a" (result) : "m" (*uaddr));
return result;
}
/* Writes BYTE to user address UDST.
UDST must be below KERN_BASE.
Returns true if successful, false if a segfault occurred.
*/
static bool
put_user (uint8_t *udst, uint8_t byte) {
int64_t error_code;
__asm __volatile (
"movabsq $done_put, %0\n"
"movb %b2, %1\n"
"done_put:\n"
: "=&a" (error_code), "=m" (*udst) : "q" (byte));
return error_code != -1;
}
์ ์ ์ฃผ์๊ฐ KERN_BASE ์๋์ ์กด์ฌํ๋ค๋ ๊ฒ ๊ฒ์ฆ๋์๋ค๊ณ ๊ฐ์
page_fault() ๋ฅผ ์์ ํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ก ์ปค๋์ page fault๋ ๋จ์ง rax๋ฅผ -1๋ก ์ค์ ํ๊ณ , ์ด์ ์ด์ ๊ฐ์ %rip๋ก ๋ณต์ฌํ๋ค๊ณ ๊ฐ์
(x86-64 ์์คํ ์์์ ํธ์ถ ๊ท์ฝ)
" process_exec()
ํจ์์ ์๋ โ์ ์ ํ๋ก๊ทธ๋จโ์ ์ํ ์ธ์๋ฅผ ์ธํ
ํ๊ธฐ "
- ์ ์ -๋ ๋ฒจ ์ดํ๋ฆฌ์ผ์ด์ ์
%rdi
,ย%rsi
,ย%rdx
,ย%rcx
,ย%r8
,ย%r9
์ํ์ค๋ค์ ์ ๋ฌํ๊ธฐ ์ํด ์ ์ ๋ ์ง์คํฐ๋ฅผ ์ฌ์ฉ
(7๊ฐ ์ด์์ Stack์ ์์)2-1. ํธ์ถ์๋ ๋ค์ ์ธ์คํธ๋ญ์ ์ ์ฃผ์(๋ฆฌํด ์ด๋๋ ์ค)๋ฅผ ์คํ์ ํธ์
2-2. ํผํธ์ถ์์ ์ฒซ๋ฒ์งธ ์ธ์คํธ๋ญ์ ์ผ๋ก ์ ํ (CALL (x86-64 ์ธ์คํธ๋ญ์ )
:๋ ๊ฐ์ง๋ฅผ ๋ชจ๋ ์ํ)
- ํผํธ์ถ์๊ฐ ์คํ
- ๋ง์ฝ ํผํธ์ถ์๊ฐ ๋ฆฌํด ๊ฐ์ ๊ฐ์ง๊ณ ์๋ค๋ฉด, ๋ฆฌํด ๊ฐ์ ๋ ์ง์คํฐ
RAX
์ ์ ์ฅ
- ํผํธ์ถ์๋ x86-64 ์ธ์คํธ๋ญ์ ์ธ
RET
(๋ฆฌํด)๋ฅผ ์ฌ์ฉํด์, ์คํ์ ๋ฐ์๋ ๋ฆฌํด ์ด๋๋ ์ค๋ฅผ popํ๊ณ ๊ทธ ์ฃผ์๊ฐ ๊ฐ๋ฆฌํค๋ ๊ณณ์ผ๋ก ์ ํํจ์ผ๋ก์จ ๋ฆฌํด
int myFunction(int a, int b, int c) {
// a, b, c๋ฅผ ์ฌ์ฉ // 2-2. ํผํธ์ถ์์ ์ฒซ๋ฒ์งธ ์ธ์คํธ๋ญ์
์ผ๋ก ์ ํ -> 3. ์คํ
return 0 // 4. RAX ์ return ๊ฐ ์ ์ฅ
} // 5. RET(๋ฆฌํด)๋ฅผ ์ฌ์ฉํด, Stack์ ๋ฐ์๋ ๋ฆฌํด ์ด๋๋ ์ค๋ฅผ pop
// ๊ทธ ์ฃผ์๊ฐ ๊ฐ๋ฆฌํค๋ ๊ณณ์ผ๋ก ์ ํํจ์ผ๋ก์จ ๋ฆฌํด
int main() {
int x = 1, y = 2, z = 3;
myFunction(x, y, z); // 1. x, y, z ๊ฐ์ด %rdi, %rsi, %rdx ๋ ์ง์คํฐ์ ์ ๋ฌ
yourFunction(); // 2-1. ๋ค์ ์ธ์คํธ๋ญ์
์ ์ฃผ์๋ฅผ Stack์ push
return 0;
}
ใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
กใ
ก
3. ํผํธ์ถ์๊ฐ ์คํ
+----------------+
stack pointer --> 0x4747fe70 | return address |
+----------------+
RDI: 0x0000000000000001 | RSI: 0x0000000000000002 | RDX: 0x0000000000000003
void
_start (int argc, char *argv[]) {
exit (main (argc, argv));
}
_start()
ํจ์๋ฅผ ์ ์ ํ๋ก๊ทธ๋จ์ ์์ ํฌ์ธํธ๋ก ์ง์ main()
์ ๋ฆฌํด๋๋ฉด์ exit()
์ ํธ์ถ์ปค๋์ ์ ์ ํ๋ก๊ทธ๋จ์ด ์คํ๋๋ ๊ฒ์ ํ๊ฐํ๊ธฐ ์ ์,
๋ ์ง์คํฐ์ ์ฌ๋ผ๊ฐ ์๋ ์ด๊ธฐ ํจ์ ๋ฅผ ์ํ ์ธ์ ๋ฅผ ๋ฐ๋์ ๋ฃ์ด์ค์ผ ํ๋ค.
ex. /bin/ls -l foo bar ๋ช
๋ น์ด ์ฃผ์ด์ง
int main(int argc, char *argv[])
- ๋ช ๋ น์ ๋จ์ด๋ค๋ก ์ชผ๊ฐ๊ธฐ :
/bin/ls
,ยl
,ยfoo
,ยbar
- ๋จ์ด๋ค์ ์คํ์ ๋งจ ์ฒ์ ๋ถ๋ถ์ ๋๊ธฐ ( ํฌ์ธํฐ์ ์ํด ์ฐธ์กฐ๋ ๊ฒ์ด๋ฏ๋ก ์์ ์๊ด X )
๊ฐ ๋ฌธ์์ด์ ์ฃผ์ + ๊ฒฝ๊ณ์กฐ๊ฑด์ ์ํ ๋ํฌ์ธํฐ ๋ฅผ
Stack
์ ์ค๋ฅธ์ชฝโ์ผ์ชฝ ์์๋กpush
- ์ด๋ค์
argv
์ ์์๊ฐ ๋๋ค.- ๋ํฌ์ธํฐ ๊ฒฝ๊ณ :
argv[argc]
๊ฐ ๋ํฌ์ธํฐ๋ผ๋ ๊ฒ์ ๋ณด์ฅํจ (C์ธ์ด ํ์ค์ ์๊ตฌ์ฌํญ)argv[0]
์ด ๊ฐ์ฅ ๋ฎ์ ๊ฐ์ ์ฃผ์๋ฅผ ๊ฐ์ง- ์ฑ๋ฅ์ ์ํด
Stack
์ ์ฒซpush
๊ฐ ๋ฐ์ํ๊ธฐ ์ ์ ์คํํฌ์ธํฐ๋ฅผ 8์ ๋ฐฐ์๋ก ๋ฐ์ฌ๋ฆผํ๊ธฐ
( word ํฌ๊ธฐ์ ์ ๋ ฌ๋ ์ ๊ทผ์ด ์ ๋ ฌ๋์ง ์์ ์ ๊ทผ๋ณด๋ค ๋น ๋ฅด๊ธฐ ๋๋ฌธ )
%rsi
๊ฐargv
์ฃผ์(argv[0]
์ฃผ์)๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ํ๊ณ ,%rdi
๋ฅผargc
๋ก ์ค์
- ๋ง์ง๋ง์ผ๋ก ๊ฐ์ง โ๋ฆฌํด ์ด๋๋ ์คโ๋ฅผ ํธ์ํฉ๋๋ค : entry ํจ์๋ ์ ๋ ๋ฆฌํด๋์ง ์๊ฒ ์ง๋ง, ํด๋น ์คํ ํ๋ ์์ ๋ค๋ฅธ ์คํ ํ๋ ์๋ค๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ ธ์ผ ํฉ๋๋ค.