๐Ÿงญ KAIST JUNGLE/Pintos

[PintOS] User Program - System Call (Project 2, TIL)

seungineer = seungwoo + engineer 2024. 5. 8. 20:33

KAIST PintOS ๊ฐ•์˜ ๋ฐ Instruction, ํ•œ์–‘๋Œ€ PintOS Slides๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉฐ ํ•™์Šตํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

ํ•™์Šต ๋„์ค‘ ์ž‘์„ฑํ•œ ๋‚ด์šฉ์ด๋ผ ํ‹€๋ฆฐ ๋‚ด์šฉ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๋“ค์–ด๊ฐ€๊ธฐ ์ „์—

๋ ˆ์ง€์Šคํ„ฐ ์—ญํ•  ์ •๋ฆฌ

  1. %rax : system call number ์ €์žฅ โ–ถ๏ธ ์šด์˜์ฒด์ œ๊ฐ€ ์–ด๋–ค ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์ˆ˜ํ–‰ํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋จ
  2. %rdi, %rsi, %r10, % r8, %r9 : system call arguments ์ „๋‹ฌ์— ์‚ฌ์šฉ(ํ˜ธ์ถœ์— ๋”ฐ๋ผ ์ผ๋ถ€๋งŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ˆœ์„œ๋Œ€๋กœ ํ• ๋‹น๋จ)
  3. %rcx : syscall ๋ช…๋ น์–ด ์‚ฌ์šฉ ์‹œ %rcx ๋ ˆ์ง€์Šคํ„ฐ์— ๋ณต๊ท€ ์ฃผ์†Œ๊ฐ€ ์ €์žฅ๋จ(์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‹œ์—๋Š” ์Šคํƒ์— ์ €์žฅ!) โฌ…๏ธ ์šด์˜์ฒด์ œ์—์„œ ์ž๋™ ์ฒ˜๋ฆฌ
  4. %r11 : syscall ๋ช…๋ น์–ด ์‚ฌ์šฉ ์‹œ ํ˜„์žฌ process state๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฆฌํ”Œ๋ž˜๊ทธ(RFLAGS ๋ ˆ์ง€์Šคํ„ฐ ๊ฐ’)๊ฐ€ ์ €์žฅ๋จ. ์‹œ์Šคํ…œ ํ˜ธ์ถœ ๊ฐ„ process state๋ฅผ ๋ณด์กดํ•˜๋Š” ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ๋จ โฌ…๏ธ ์šด์˜์ฒด์ œ์—์„œ ์ž๋™ ์ฒ˜๋ฆฌ

Exception ์ฒ˜๋ฆฌ

Exception(์˜ˆ์™ธ)์ด๋ž€ ์ฝ”๋“œ ์‹คํ–‰ ์ค‘์— ์–ด๋–ค ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค. ์ฆ‰, ์ •์ƒ ํ๋ฆ„์„ ๋ฐฉํ•ดํ•˜๋Š” ๊ฒƒ์œผ๋กœ page fault ํ˜น์€ 0์œผ๋กœ ๋‚˜๋ˆ„๋Š” ํ–‰์œ„(divide by zero)์™€ ๊ฐ™์€ ์˜ค๋ฅ˜(๋‚ด๋ถ€ ์ธํ„ฐ๋ŸฝํŠธ)๋ฅผ ๋“ค ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋Š” ์šด์˜ ์ฒด์ œ์—์„œ ๋‹ด๋‹นํ•œ๋‹ค. Project1์—์„œ๋Š” ์™ธ๋ถ€ ์ธํ„ฐ๋ŸฝํŠธ๋ฅผ ์šด์˜ ์ฒด์ œ๊ฐ€ ํƒ€์ด๋จธ์™€ I/O interrupts๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ๋‹ค๋ฃจ์—ˆ๋‹ค. Project2์—์„œ๋Š” user program์ด ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜์œผ๋กœ ์šด์˜ ์ฒด์ œ์— ์„œ๋น„์Šค(halt, exit, open ๋“ฑ)๋ฅผ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์„ ๊ตฌํ˜„ํ•˜๋ฉฐ System Call์ด๋ผ๊ณ  ํ•œ๋‹ค.

x86-64 ์•„ํ‚คํ…์ฒ˜์—์„œ์˜ System Call

x86-64 ์•„ํ‚คํ…์ฒ˜์—์„œ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์œ„ํ•œ ๋ช…๋ น์–ด์ธ syscall์ด ๋„์ž…๋˜์—ˆ๋‹ค. ์ด ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด system call handler๋ฅผ ๋น ๋ฅด๊ฒŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. syscall ๋ช…๋ น์–ด ์‚ฌ์šฉ ์‹œ system call number์™€ ์ถ”๊ฐ€ arguments๋Š” ๋ ˆ์ง€์Šคํ„ฐ์— ์„ค์ •๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค(์ฐธ๊ณ  : Linux system call table ์ •๋ฆฌ).

System Call Handling

syscall_handler()๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด, system call number๋Š” %rax, ์—ฌํƒ€ arguments๋Š” ์ˆœ์„œ๋Œ€๋กœ %rdi, %rsi, %rdx, %r10, %r8, %r9 ์ˆœ์„œ๋Œ€๋กœ ํ• ๋‹น๋œ๋‹ค. x86-64 convention์— ๋”ฐ๋ผ ํ•จ์ˆ˜ ๋ฐ˜ํ™˜ ๊ฐ’์€ RAX ๋ ˆ์ง€์Šคํ„ฐ์— ์œ„์น˜๋˜๋ฉฐ, return ๊ฐ’์ด ์žˆ๋Š” ์‹œ์Šคํ…œ ํ˜ธ์ถœ์€ intr_frame์˜ rax ๋ฉค๋ฒ„(%rax)๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ’ก x86-64 ์•„ํ‚คํ…์ณ์—์„œ๋Š” syscall ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด system call์„ ์œ„ํ•œ syscall_handler๋ฅผ ๋น ๋ฅด๊ฒŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๊ณ , system call number์™€ arguments๋Š” ์ •ํ•ด์ง„ ๋ ˆ์ง€์Šคํ„ฐ์— ์„ค์ •๋˜์–ด ์ „๋‹ฌ๋œ๋‹ค. ์‹œ์Šคํ…œ ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋Š” RAX ๋ ˆ์ง€์Šคํ„ฐ์— return ๋˜๋ฉฐ ์ด๋Š” intr_frame์˜ %rax ์ˆ˜์ •์œผ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

์ฝ”๋“œ๋กœ ์‚ดํŽด๋ณด๊ธฐ

main() ํ•จ์ˆ˜์˜ msg()์—์„œ vmsg() ๋‚ด ์–ด๋–ค system call์„ ํ˜ธ์ถœํ•˜๋ฉด(halt() ๊ฐ€์ •)

1๏ธโƒฃ syscall.c์—์„œ halt() ํ•จ์ˆ˜ ํ˜ธ์ถœ

void
halt (void) {
	syscall0 (SYS_HALT);
	NOT_REACHED ();
}

2๏ธโƒฃ syscall0 (SYS_HALT);

/* Invokes syscall NUMBER, passing no arguments, and returns the
   return value as an `int'. */
#define syscall0(NUMBER) ( \
		syscall(((uint64_t) NUMBER), 0, 0, 0, 0, 0, 0))
/* System call numbers. */
enum {
	/* Projects 2 and later. */
	SYS_HALT,                   /* Halt the operating system. */
	SYS_EXIT,                   /* Terminate this process. */
	SYS_FORK,                   /* Clone current process. */
	SYS_EXEC,                   /* Switch current process. */
	SYS_WAIT,                   /* Wait for a child process to die. */
	SYS_CREATE,                 /* Create a file. */
	SYS_REMOVE,                 /* Delete a file. */
	SYS_OPEN,                   /* Open a file. */
	SYS_FILESIZE,               /* Obtain a file's size. */
	SYS_READ,                   /* Read from a file. */
	SYS_WRITE,                  /* Write to a file. */
	SYS_SEEK,                   /* Change position in a file. */
	SYS_TELL,                   /* Report current position in a file. */
	SYS_CLOSE,                  /* Close a file. */
    ...
    }

syscall0 (SYS_HALT); ๋Š” syscall0 (3); ์ด๋ผ๋Š” ๊ฒƒ์œผ๋กœ ๊ฒฐ๊ตญ #define์— ๋”ฐ๋ผ syscall(3, 0, 0, 0, 0, 0, 0)์ด ํ˜ธ์ถœ๋œ๋‹ค.

3๏ธโƒฃ syscall()

__attribute__((always_inline))
static __inline int64_t syscall (uint64_t num_, uint64_t a1_, uint64_t a2_,
		uint64_t a3_, uint64_t a4_, uint64_t a5_, uint64_t a6_) {
	int64_t ret;
	/* system call arguments๋ฅผ binding ํ•จ */
	register uint64_t *num asm ("rax") = (uint64_t *) num_;
	register uint64_t *a1 asm ("rdi") = (uint64_t *) a1_;
	register uint64_t *a2 asm ("rsi") = (uint64_t *) a2_;
	register uint64_t *a3 asm ("rdx") = (uint64_t *) a3_;
	register uint64_t *a4 asm ("r10") = (uint64_t *) a4_;
	register uint64_t *a5 asm ("r8") = (uint64_t *) a5_;
	register uint64_t *a6 asm ("r9") = (uint64_t *) a6_;

	__asm __volatile(
			"mov %1, %%rax\n"
			"mov %2, %%rdi\n"
			"mov %3, %%rsi\n"
			"mov %4, %%rdx\n"
			"mov %5, %%r10\n"
			"mov %6, %%r8\n"
			"mov %7, %%r9\n"
			"syscall\n"
			: "=a" (ret)
			: "g" (num), "g" (a1), "g" (a2), "g" (a3), "g" (a4), "g" (a5), "g" (a6)
			: "cc", "memory");
	return ret;
}
  • system call arguments ์ค‘ ์ธ์ž๋กœ ์‚ฌ์šฉ๋  ๊ฐ’ ์ค‘ ์ฒซ ๋ฒˆ์งธ ๊ฐ’(num_)์ด 'rax'์— binding ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ
  • ๋‚˜๋จธ์ง€ ์ธ์ž๋Š” ์ˆœ์„œ๋Œ€๋กœ rdi, rsi, rdx ,..., r9์— binding ๋จ
  • __asm __volatile ๋กœ ํ•ญ์ƒ ๋ช…์‹œ๋œ ์ˆœ์„œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋„๋ก ํ•จ
  • mov ๋ช…๋ น์–ด๋กœ ๋ฏธ๋ฆฌ ์ •์˜๋œ ๋ ˆ์ง€์Šคํ„ฐ์— ํ• ๋‹น
  • syscall ๋ช…๋ น์–ด๋กœ ์‹ค์ œ system call์ด ์ˆ˜ํ–‰๋จ(์ด์ œ์•ผ CPU๋Š” ์ปค๋„ ๋ชจ๋“œ ์ „ํ™˜)
  • syscall ๊ฒฐ๊ณผ๋Š” ret ๋ณ€์ˆ˜์— ๋‹ด๊ฒจ caller์— ๋ฐ˜ํ™˜๋จ

4๏ธโƒฃ "syscall\n"

#include "threads/loader.h"

.text
.globl syscall_entry
.type syscall_entry, @function
syscall_entry:
	movq %rbx, temp1(%rip)
	movq %r12, temp2(%rip)     /* callee saved registers */
	movq %rsp, %rbx            /* Store userland rsp    */
	movabs $tss, %r12
	movq (%r12), %r12
	movq 4(%r12), %rsp         /* Kernel Stack ์ง„์ž…! */
	/* Now we are in the kernel stack */
	push $(SEL_UDSEG)      /* if->ss */
	push %rbx              /* if->rsp */
	push %r11              /* if->eflags */
	push $(SEL_UCSEG)      /* if->cs */
	push %rcx              /* if->rip */
	subq $16, %rsp         /* skip error_code, vec_no */
	push $(SEL_UDSEG)      /* if->ds */
	push $(SEL_UDSEG)      /* if->es */

movq ๋ช…๋ น์„ ํ†ตํ•ด %rsp๊ฐ€ kernel stack์œผ๋กœ ์ด๋™ํ•œ๋‹ค. ๋“œ๋””์–ด user stack์—์„œ kernel stack์œผ๋กœ ์ง„์ž…ํ•˜๊ฒŒ ๋๋‹ค! ์ด ๋ช…๋ น์–ด๋Š”  syscall-entry.S์— ์žˆ๋‹ค. '.S' ํŒŒ์ผ์€ C์–ธ์–ด๋กœ ์ž‘์„ฑ๋œ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์–ด์…ˆ๋ธ”๋ฆฌ ์–ธ์–ด ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ํŒŒ์ผ์ด๋‹ค. ์ „์ฒ˜๋ฆฌ๊ธฐ์—์„œ ์ฒ˜๋ฆฌ๋˜๋ฉฐ C์–ธ์–ด์˜ ์ „์ฒ˜๋ฆฌ๊ธฐ ์ง€์‹œ๋ฌธ(#include, #define ๋“ฑ)์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • movq 4(%r12), %rsp : r12์—์„œ 4 byte๋ฅผ ๋”ํ•œ ์ฃผ์†Œ๋กœ rsp๋ฅผ ์ด๋™์‹œํ‚ด(x86-64 ์•„ํ‚คํ…์ฒ˜์ด๋ฏ€๋กœ 8๋ฐ”์ดํŠธ ๋‹จ์œ„๊ฐ€ ๋˜์–ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์€๋ฐ.. ์ถ”ํ›„์— ์‚ดํŽด๋ณผ ์˜ˆ์ •์ด๋‹ค ๐Ÿค”)

์œ„ ๊ณผ์ •์„ ๊ฑฐ์ณ์„œ syscall_handler() ํ•จ์ˆ˜๋กœ ๋„˜์–ด๊ฐ€๊ฒŒ ๋˜๋ฉฐ, kernel ๋‹จ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

 


System Call Handler

  1. User stack pointer(rsp)์™€ system call arguments๊ฐ€ ์œ ํšจ ์ฃผ์†Œ ์˜์—ญ(user stack)์ธ์ง€ ํ™•์ธํ•˜๋„๋ก ๊ตฌํ˜„
  2. System call number๋ฅผ ์ด์šฉํ•˜์—ฌ ํ•ด๋‹น system call์˜ ์„œ๋น„์Šค ๋ฃจํ‹ด์„ ํ˜ธ์ถœํ•˜๋„๋ก ๊ตฌํ˜„
  3. User stack interrupt frame์˜ arguments๋ฅผ kernel stack์— ๋ณต์‚ฌ๋˜๋„๋ก ๊ตฌํ˜„
  4. System call return ๊ฐ’์„ Interrupt frame์˜ rax์— ์ €์žฅ๋˜๋„๋ก ๊ตฌํ˜„

void check_address (void *addr)

System Call Handler 1๋ฒˆ์— ํ•ด๋‹นํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.

  • ์ฃผ์†Œ ๊ฐ’์ด ์œ ์ € ์˜์—ญ ์ฃผ์†Œ ๊ฐ’์ธ์ง€ ํ™•์ธ
  • ์œ ์ € ์˜์—ญ์ด ์•„๋‹ˆ๋ผ๋ฉด process exit
void
check_address (void *addr){
	if (addr != NULL && is_user_vaddr(addr)){
		return; // ์œ ํšจํ•œ ์ฃผ์†Œ
	}
	exit (-1);      // ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ์†Œ์ผ ๋•Œ ์ฒ˜๋ฆฌ
}
  • ์ฒ˜์Œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ ์‹œ exit() ํ•จ์ˆ˜ ๋Œ€์‹  thread_exit() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์˜€์„ ์ˆ˜๋„ ์žˆ์Œ
  • pintos๋ฅผ ์™„์ „ํžˆ ์ข…๋ฃŒํ•  ๋•Œ ์กฐ๊ฑด์ด ๋ถ™๋Š” ๊ฒŒ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ถ”ํ›„ exit () ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๊ฒŒ ๋จ

ํ•œ์–‘๋Œ€ Pintos PPT์— ํ•„์š”ํ•œ ํ•จ์ˆ˜๋กœ ๋‚˜์™€ ์žˆ๋Š” 'void get_argument()' ํ•จ์ˆ˜๋Š” ๊ตฌํ˜„ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค(system call arguments๋ฅผ ์ด๋ฏธ kernel์— ๋ณต์‚ฌํ–ˆ๊ธฐ ๋•Œ๋ฌธ).

# ์ฐธ๊ณ 

make check > log.txt ๊ฒฐ๊ณผ ํ™•์ธ, ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด msg ์ถœ๋ ฅ์ด ์ „ํ˜€๋˜์ง€ ์•Š์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

System Call ๊ฐ๊ฐ์ด ์ž˜ ๊ตฌํ˜„๋˜์—ˆ๋Š”์ง€ ํ™•์ธ('make check'๋ฅผ ํ†ตํ•œ PASS, FAIL ํ™•์ธ)์„ ์œ„ํ•ด์„œ๋Š” main.c ์˜ msg๊ฐ€ ์ถœ๋ ฅ๋˜์–ด์•ผ ํ•œ๋‹ค. ์œ„ ๊ทธ๋ฆผ์—์„œ ์ฒ˜๋Ÿผ output ๋น„๊ต๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์ธ๋ฐ, ํ˜„์žฌ ๋ถ€๋ชจ process๋Š” ์ž์‹ process๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ณง๋ฐ”๋กœ ์ข…๋ฃŒ๋˜๋ฏ€๋กœ msg๊ฐ€ ์ถœ๋ ฅ๋  ์ˆ˜ ์—†๋‹ค. ๋‹น์—ฐํ•˜๊ฒŒ๋„ FAIL์ด ๊ณ„์† ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค.

 

halt()

System Call Handler 2, 3, 4๋ฒˆ์— ํ•ด๋‹นํ•˜๋Š” ๊ตฌํ˜„๋‚ด์šฉ์ด๋‹ค.

syscall_handler (struct intr_frame *f UNUSED) {
	// TODO: Your implementation goes here.
	int syscall_number = f->R.rax; // system call number ๊ฐ€์ ธ์˜ค๊ธฐ
	switch (syscall_number){
		case SYS_HALT:
			halt();
			break;
        	...
		case SYS_WAIT:
			f->R.rax = wait(f->R.rdi); // return ๊ฐ’ ํ˜„์žฌ rax์— ์ €์žฅ
			break;
	}
  • f->R.rax์˜ system call number๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ , ์ด number์— ๋งž๋Š” ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ์„œ๋น„์Šค ๋ฃจํ‹ด ๊ตฌ์„ฑ
  • System call return ๊ฐ’์ด ์žˆ๋Š” ๊ฒฝ์šฐ ํ˜„์žฌ rax์— ์ €์žฅ

halt() ํ•จ์ˆ˜๋Š” pintos๋ผ๋Š” ์šด์˜์ฒด์ œ๋ฅผ ์ข…๋ฃŒ์‹œํ‚ค๋Š” ํ•จ์ˆ˜์ด๋‹ค.

void
halt (void){
	power_off (); // pintos ์™„์ „ํžˆ ์ข…๋ฃŒ
}

 

์ด๋ ‡๊ฒŒ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„๋œ๋‹ค.

exit()

ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒ์‹œํ‚ค๋Š” system call์ด๋‹ค.

  • Process Termination Message : "ํ”„๋กœ์„ธ์Šค ์ด๋ฆ„: exit(status)"
  • ์ •์ƒ ์ข…๋ฃŒ ์‹œ status๋Š” 0
void
exit (int status){
	struct thread *curr = thread_current();
	curr->status = status;
	printf("%s(ํ”„๋กœ์„ธ์Šค ์ด๋ฆ„): exit(%d)\n",curr->name, status); // process termination message
	thread_exit();
}

check_address()์—์„œ ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ์†Œ์ธ ๊ฒฝ์šฐ exit (-1)์œผ๋กœ process๋ฅผ exit ํ•ด์•ผํ•˜๋Š” ์ด์œ ๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

create()

์ž…๋ ฅ ๋ฐ›์€ file ์œ„์น˜์— initial_size ๋งŒํผ ํ• ๋‹นํ•˜๋Š” system call์ด๋‹ค.

bool
create (const char *file, unsigned initial_size){ // ํŒŒ์ผ ์‹œ์Šคํ…œ ์ƒ์„ฑ ์‹œ์Šคํ…œ ์ฝœ
	check_address(file);                      // ์œ ํšจํ•œ ์ฃผ์†Œ์ธ ๊ฒฝ์šฐ
	return filesys_create(file, initial_size);  
}

*๋งˆ์ฐฌ๊ฐ€์ง€๋กœ create ํ˜ธ์ถœ ์‹œ syscall_handler์˜ switch ๋ฌธ์—์„œ ๊ฑธ๋ฆฌ๋„๋ก case ์ถ”๊ฐ€ ํ•„์š”


Hierarchical Process Structure ์ „๊นŒ์ง€ ์™„๋ฃŒํ•˜์˜€๋‹ค. ์ดํ›„์—๋Š” ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜๋Š” ๊ฒƒ์„ semaphore๋ฅผ ์ด์šฉํ•ด ํ•ด๊ฒฐํ•˜์—ฌ, Pintos๋ฅผ ๋ฐœ์ „์‹œํ‚จ๋‹ค.

 

์‹œ๊ฐ„์ด ๋…น๋Š”๋‹ค HURRY UP ๐Ÿซ