PintOS PJT2 - system call handler

김수환·2024년 11월 17일

PintOS

목록 보기
9/15
/* The main system call interface */
/** #Project 2: System Call - 시스템 콜 핸들러 */
void 
syscall_handler (struct intr_frame *f UNUSED) {
    // TODO: Your implementation goes here.
    int sys_number = f->R.rax;

    // Argument 순서
    // %rdi %rsi %rdx %r10 %r8 %r9

    switch (sys_number) {
        case SYS_HALT:
            halt();
            break;
        case SYS_EXIT:
            exit(f->R.rdi);
            break;
        case SYS_FORK:
            f->R.rax = fork(f->R.rdi);
            break;
        case SYS_EXEC:
            f->R.rax = exec(f->R.rdi);
            break;
        case SYS_WAIT:
            f->R.rax = process_wait(f->R.rdi);
            break;
        case SYS_CREATE:
            f->R.rax = create(f->R.rdi, f->R.rsi);
            break;
        case SYS_REMOVE:
            f->R.rax = remove(f->R.rdi);
            break;
        case SYS_OPEN:
            f->R.rax = open(f->R.rdi);
            break;
        case SYS_FILESIZE:
            f->R.rax = filesize(f->R.rdi);
            break;
        case SYS_READ:
            f->R.rax = read(f->R.rdi, f->R.rsi, f->R.rdx);
            break;
        case SYS_WRITE:
            f->R.rax = write(f->R.rdi, f->R.rsi, f->R.rdx);
            break;
        case SYS_SEEK:
            seek(f->R.rdi, f->R.rsi);
            break;
        case SYS_TELL:
            f->R.rax = tell(f->R.rdi);
            break;
        case SYS_CLOSE:
            close(f->R.rdi);
            break;
        case SYS_DUP2:
            f->R.rax = dup2(f->R.rdi, f->R.rsi);
            break;
        default:
            exit(-1);
    }
}

코드 분석

syscall_handler 함수는 시스템 호출(System Call)을 처리하는 핵심 함수로, 사용자 공간에서 커널 공간으로 전달된 시스템 호출 번호와 매개변수에 따라 적절한 커널 함수로 요청을 분배합니다.


1. 역할

  • 인터럽트 발생 시 struct intr_frame에 저장된 시스템 호출 정보를 기반으로 적절한 시스템 호출을 실행합니다.
  • 시스템 호출 번호(sys_number)를 확인하여 호출된 시스템 함수에 매핑합니다.
  • 시스템 호출의 결과 값을 레지스터 rax에 저장해 호출한 프로세스에 반환합니다.

2. 주요 단계 분석

(1) 시스템 호출 번호 확인

c
코드 복사
int sys_number = f->R.rax;
  • 인터럽트 프레임의 rax 레지스터는 시스템 호출 번호를 저장합니다.
  • 시스템 호출 번호를 기반으로 어떤 커널 기능을 수행할지 결정합니다.

(2) 매개변수 전달 방식

시스템 호출 매개변수는 레지스터를 통해 전달됩니다:

  • 순서: %rdi, %rsi, %rdx, %r10, %r8, %r9
  • 이는 x86-64의 System V ABI(Application Binary Interface)에 따라 정의된 호출 규약입니다.

예를 들어:

  • SYS_EXIT 호출 시, exit() 함수는 첫 번째 인자를 rdi 레지스터를 통해 전달받습니다.
  • SYS_READ 호출 시, read() 함수는 세 개의 인자를 rdi, rsi, rdx를 통해 전달받습니다.

(3) 시스템 호출 처리

c
코드 복사
switch (sys_number) {
    case SYS_HALT:
        halt();
        break;
    case SYS_EXIT:
        exit(f->R.rdi);
        break;
    case SYS_FORK:
        f->R.rax = fork(f->R.rdi);
        break;
    ...
}
  • switch을 사용하여 시스템 호출 번호에 따라 적절한 커널 함수로 분기합니다.
  • f->R.rdi, f->R.rsi, f->R.rdx 등 레지스터에서 매개변수를 추출하여 커널 함수에 전달합니다.
  • 반환 값이 있는 경우 f->R.rax에 저장하여 호출 프로세스에 전달합니다.

3. 각 시스템 호출의 설명

시스템 호출 번호설명활용된 매개변수
SYS_HALT시스템 종료없음
SYS_EXIT현재 프로세스 종료rdi: 종료 코드
SYS_FORK프로세스 복제rdi: 프로세스 이름
SYS_EXEC프로그램 실행rdi: 프로그램 경로
SYS_WAIT자식 프로세스 대기rdi: 자식 프로세스 ID
SYS_CREATE파일 생성rdi: 파일 이름, rsi: 크기
SYS_REMOVE파일 삭제rdi: 파일 이름
SYS_OPEN파일 열기rdi: 파일 이름
SYS_FILESIZE파일 크기 조회rdi: 파일 핸들
SYS_READ파일 읽기rdi: 핸들, rsi: 버퍼, rdx: 크기
SYS_WRITE파일 쓰기rdi: 핸들, rsi: 버퍼, rdx: 크기
SYS_SEEK파일 위치 이동rdi: 핸들, rsi: 위치
SYS_TELL파일 현재 위치 조회rdi: 핸들
SYS_CLOSE파일 닫기rdi: 핸들
SYS_DUP2파일 디스크립터 복제rdi: 원본 핸들, rsi: 대상 핸들

4. 활용법

(1) 사용자 프로그램에서 시스템 호출

사용자는 시스템 호출 인터페이스를 통해 커널 기능을 요청합니다:

c
코드 복사
#include <syscall.h>int fd = open("test.txt");
if (fd < 0) {
    exit(-1);
}
write(fd, "Hello, Pintos!", 14);
close(fd);
  • open(), write(), close() 등은 시스템 호출 인터페이스를 통해 syscall_handler로 전달됩니다.

(2) 커널의 시스템 호출 구현

  • syscall_handler는 위와 같은 시스템 호출을 인터럽트 프레임에서 읽어 처리합니다.
  • 예를 들어, SYS_WRITE의 경우 write() 커널 함수를 호출하여 파일 시스템의 쓰기 작업을 수행합니다.

(3) 예외 처리

  • 정의되지 않은 시스템 호출 번호는 default 분기로 이동하여 프로그램을 종료합니다:
c
코드 복사
default:
    exit(-1);

5. 결론

이 코드는 사용자 프로그램과 커널 사이의 인터페이스를 구현한 중요한 모듈입니다. 시스템 호출 번호에 따라 적절한 커널 함수로 요청을 분배하며, 매개변수 전달과 결과 반환을 위한 구조를 효율적으로 처리합니다. 이를 통해 사용자 프로그램은 커널 기능을 간단하게 사용할 수 있습니다.

profile
juniorDev

0개의 댓글