[PintOS] System Call을 실행하는 과정

Serye·2023년 5월 8일
2

운영체제

목록 보기
4/7
post-thumbnail

서론

오늘을 끝으로 2.5주간의 PintOS 프로젝트가 끝이 났다. 시스템 콜이 무엇인지는 이번 주차 시작에 정리를 했고, 쉬운 코드의 시스템 콜 영상을 통해 큰 틀은 이해했다. 하지만 구체적으로 어떤 코드를 통해, 어떤 함수를 통해 해당 과정이 진행되냐고 물어본다면 설명을 할 수가 없었다.(어떻게 되겠지... 하지만 컴퓨터에 자동으로 어떻게 되는 건 없다.) 그렇게 흐릿하게 큰 틀만 안 상태로 구현을 했고, 발표를 준비하면서 해당 부분에 대해 확실히 다루는 게 어떤가 제의해보았다. 그렇게 마지막 날에 팀원과 코드를 뜯어보기 시작했고, 정확한 지점을 알 수 있었다.

System Call의 개략도

유저 함수

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

void exit(int status)
{
	syscall1(SYS_EXIT, status);
	NOT_REACHED();
}

pid_t fork(const char *thread_name)
{
	return (pid_t)syscall1(SYS_FORK, thread_name);
}

...

유저가 호출하는 시스템 콜을 필요로 하는 함수이다.

syscallN( )

#define syscall0(NUMBER) ( \
	syscall(((uint64_t)NUMBER), 0, 0, 0, 0, 0, 0))

#define syscall1(NUMBER, ARG0) ( \
	syscall(((uint64_t)NUMBER),  \
			((uint64_t)ARG0), 0, 0, 0, 0, 0))
...

시스템 콜 번호와 인자를 받는 함수로 인자의 개수에 따라 다르다. 인자의 개수는 최대 6개이다.

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_)
{
	...

	__asm __volatile(
		...
        
		"syscall\n"
		: "=a"(ret)
		: "g"(num), "g"(a1), "g"(a2), "g"(a3), "g"(a4), "g"(a5), "g"(a6)
		: "cc", "memory");
	return ret;
}

위 함수의 "syscall\n" 부분은 현재 실행 중인 프로세스를 커널 모드로 전환시키고, userprog/syscall-entry.S의 syscall_entry flag로 이어진다.

syscall_entry.S

...

no_sti:
	movabs $syscall_handler, %r12
	call *%r12
    
...

위의 어셈블리어 코드에서 syscall_handler 함수의 주소를 %r12 레지스터에 저장하고, 호출한다.

syscall_handler( )

void syscall_handler(struct intr_frame *f)
{
	switch (f->R.rax) 
	{
	case SYS_HALT:
		halt();
		break;
	case SYS_EXIT:
		exit(f->R.rdi);
		break;
	case SYS_FORK:
		f->R.rax = fork(f->R.rdi, f);
		break;
    }
}

시스템 콜 번호에 맞는 시스템 콜 함수를 호출한다.

시스템 콜 함수

void halt(void)
{
	power_off();
}

void exit(int status)
{
	struct thread *cur = thread_current();
	cur->exit_status = status;
	printf("%s: exit(%d)\n", thread_name(), status);
	thread_exit(); 
}

tid_t fork(const char *thread_name, struct intr_frame *f)
{
	return process_fork(thread_name, f);
}
profile
🎤 📷 ❄️ 🌊

0개의 댓글