컴퓨터 프로그래밍

[Pintos Project 2] System call handler

THINK_PRO 2014. 4. 15. 13:43

(프로젝트 개요)


현재 pintos는 시스템 콜 핸들러가 제대로 구현되어 있지 않다. 시스템 콜이 발생해도 system call!! 이라는 출력문 하나만 달랑 뿌리고, 그대로 스레드가 종료된다.(thread_exit()) 따라서, 이번 프로젝트 2는 핀토스의 시스템 콜 핸들러 함수를 구현하고, 간단한 시스템 콜(halt, exit, create, remove)를 구현해본다.



| 시스템 콜?

사용자 모드 수준에서의 프로그램이 커널 기능을 사용할 수 있도록 해주는 인터페이스.

시스템 콜의 기능들은 커널 모드에서 실행되고, 처리 후 사용자 모드로 복귀됨.



(프로젝트 해결 방법 개요)


우선, 2가지 함수를 구현해야 함. 


1. 특정 포인터(주소값)가 유저 영역에 존재하는지 확인하는 함수.

void check_address(void * address);


2. 유저 스택에 들어 있는 인자들의 주소를 저장하는 함수.

void get_argument(void *esp, void *arg, int count);


1. 유저 영역은 0x08048000 에서 0xc0000000 사이에 (경계값 제외) 존재하는 주소값이면 유저 영역인 것이다. check_address를 구현할 때 이 바깥 범위의 값이면 exit (-1)을 호출해 프로그램을 종료시켜야 한다. (유저 영역이 아닌 커널 영역을 건드리는 프로그램은 프로그램을 종료시키는 것이 적절한 운영체제의 반응이다.)


2. get_argument 의 함수는 esp 인자에서 인자들을 4바이트씩 긁어온 후, arg라는 변수에 저장하는 행동을 한다. 참고로, arg에 저장하는 값들은 인자의 주소값이다. (이 부분을 정확히 이해하라.) arg에 주소값을 저장하지 않고 인자값 자체를 저장하면 안된다. 왜냐하면, 시스템 콜의 인자들이 전부 4바이트로 표현할 수 있다는 보장이 없기 떄문이다. (가령 문자열이 전달되어 온다면 어떻게 할것인가..? 해결방법은 문자열 자체의 주소값을 저장하는 것이다.)


따라서, arg에는 반드시 인자의 주.소.값이 저장되어야 함을 무한 강조!!

f->esp 의 첫 4바이트는 시스템 콜 넘버이므로, 그 다음 4바이트씩 count 횟수만큼 긁어와서 arg에 저장하면 된다.



============

시스템 콜 핸들러 함수

static void syscall_handler (struct intr_frame *f UNUSED) { /* 유저 스택에 저장되어 있는 시스템 콜 넘버를 이용해 시스템 콜 핸들러 구현 */ /* 스택 포인터가 유저 영역인지 확인 */ /* 저장된 인자 값이 포인터일 경우 유저 영역의 주소인지 확인*/

}

f->esp (유저 스택)에는 4바이트씩 인자들이 저장되어 있다. f->esp의 첫 번째 4바이트에는 시스템 콜의 넘버가 저장되어 있고, 그 뒤로 4바이트씩 시스템 콜의 인자가 저장되어 있다.


예를 들어, create 시스템 콜은 인자로 파일 이름과 파일의 첫 크기를 인자로 받는다. 그러면, create 시스템 콜이 발생할 때 유저 스택 포인터는

다음과 같은 구조를 띈다.


f->esp

(4바이트) 4

(4바이트) 0x100

(4바이트) 0x104

....

0x100은 파일 이름 문자열의 주소값이고, 0x104는 파일의 첫 크기의 주소값이다. 물론, 파일의 첫 크기값은 정수일테지만, 정수값 자체를 유저 스택에 저장하지 않는다. 유저 스택에는 '주소값'이 저장되어 있음을 무조건 기억하라. 따라서, 나중에 시스템 콜 핸들러에서 create 시스템 콜을 처리할 때 다음과 같이 처리해야 한다.


    case SYS_CREATE:/* 4 */
      f->eax = create((char *)*(int *)arg[0], (unsigned)*(int *)arg[1]);
    break;

현재 arg에는 인자들의 '주소값'이 저장되어 있다. 즉, arg[0], arg[1],...등은 전부 '주소값'이다. 따라서, *arg[0]의 의미는, arg의 첫 번째 값의 내용물을 찾아오는 것이다. 따라서, 첫 번째 인자의 주소값의 내용물을 찾아와서 그들을 시스템 콜 함수의 인자로 넘겨줘야 하는 것이다.