xv6 - System call
시스템콜 과정
1. 사용자 프로그램에서 myfunction() 사용
2. user.h에 myfunction()함수가 선언되어있으며
usys.S에 링크되어 있다.(여기서 .S는 어셈블리어)
3. usys.S에 어셈블리 코드로
#include "syscall.h" <- 여기에 SYS_myfunction의 번호가 저장되어있다.
#define SYSCALL(name) <- myfunction()의 정의가 이 부분이다.(유저 영역에서의 시스템콜은 모두 옆처럼 정의 되어 있다.)
.globl name;
name:
movl $SYS_ ## name, %eax;
int $T_SYSCALL; <- interrupt로 64를 호출
ret
즉, 유저 영역에서 사용되는 시스템콜의 정의는 단순히 번호를 eax에 넣고 인터럽트를 발생하는 것
4. int $T_SYSCALL;로 인해 syscall.c의 syscall()함수가 호출됨
eax의 값을 보고 어떤 SYS_<...> 번호가 호출됬는지 알아냄 <- syscall.h에 번호로 저장되어있음
우선, syscalls[]에 index로 SYS_<...>를 넘겨주면 해당 함수의 포인터를 반환
static int (*syscalls[])(void) = {
[SYS_myfunction] sys_myfunction,
...
}
5. 커널 모드의 시스템 콜과 이의 wrap 함수인 sys_myfunction()은 defs.h에 선언되어 있다.
유저 모드의 시스템 콜을 호출할 때 사용되었던 인자들은 유저 스택에 쌓여있고, 현재는 커널 모드이기 때문에 커널 스택에 있다.
따라서 유저 스택에 접근해서 인자들을 가져올 필요가 있고, 이때 argstr을 통해서 유저 스택에 저장되어있는 인자들을 가져올 수 있다.
바로 커널 모드의 시스템 콜을 사용하기 보다 wrap 함수를 통하여 인자들을 가져온 뒤, 커널 모드의 시스템 콜을 호출하면 된다.
(defs.h는 커널 영역에서 사용되는 시스템 콜을 위한 헤더 파일이다.)