개요
교육용 OS로 개발된 XV6의 시스템 콜 호출 과정을 알아보겠습니다.
시스템 콜은 커널 작업을 안전하게 수행할 수 있게 유저에게 제공하는 OS API 입니다.
시스템 콜 정의
usys.S
SYSCALL(name)
매크로를 통해 name
에 해당하는 시스템 콜을 정의합니다.
movl $SYS_ ## name, $eax;
는 syscall.h
에 정의되어 있는 SYS_name
에 해당하는 번호를 eax
레지스터에 저장합니다.
이 값은 나중에 시스템 콜 포인터 함수를 검색할 때 키 값으로 사용됩니다.
참고)) ##은 왼쪽 토큰을 오른쪽 토큰에 붙히는 명령어 입니다.
syscall.h
int $T_SYSCALL
는 시스템 콜 인터럽트를 발생시킵니다.
T_SYSCALL
상수는 trap.h
에 정의 되어 있습니다.
trap.h
xv6에서 $T_SYSCALL은 64로 정의되어 있습니다.
int $T_SYSCALL
는 64번째 벡터를 가리키게 됩니다.
IDT
vectors.S
vectors.S
는 vectors.pl
을 실행시키면 생성됩니다.
이것은 trap.c
에서 IDT를 초기화 할 때 사용됩니다.
IDT 초기화(trap.c)
IDT(Interupt Data Table)는 인터럽트의 정보가 담겨져 있는 테이블입니다.
IDT에는 alltraps
분기하는 코드가 있습니다.
alltraps
의 정의는 trapasm.S
에 있습니다.
trapasm.S
alltraps
로 분기하게 되면 트랩에 필요한 스택 프레임을 쌓고 call trap
을 실행합니다.
trap()
trap.c
trapframe
구조체의 trapno
(트랩 번호)를 확인하여 T_SYSCALL
(64)이면 syscall()
을 호출 합니다.
syscall()
syscall.c
syscall()
은 매핑된 함수 포인터를 호출합니다.
defs.h
헤더 파일에 sys_
함수들이 선언 되어 있고
프로세스 관련 시스템 콜 정의는 sysproc.c
, 파일 관련 시스템 콜 정의는 sysfile.c
에 있습니다.
XV6 시스템 콜 요약
리눅스와의 차이
리눅스(2.4 버전)에서는 entry.S 파일에서 system call을 호출하는데, xv6는 syscall.c에서 호출합니다.