지난번까지의 과제에서 실행한 모든 코드는 커널의 일부로서 시스템에 중요한 부분에 접근 할 수 있는 특권을 가지고 실행되었다. 하지만 유저 프로그램을 실행하기 시작하면 더 이상 그런 특권은 갖지 못한다. 지금부터의 과제는 이런 상황을 다뤄야 한다.
pintOS에서의 프로세스는 하나의 스레드만을 가질 수 있다.(멀티스레드 프로세스 지원 X)
이러한 상황에서 우리는 한번에 하나 이상의 프로그램이 실행될 수 있도록 할 것이다. 이는 우리가 한번에 여러 프로세스들을 로드하고 실행할 때 메모리, 스케쥴링, 그 외 다른 상태들을 모두 관리해야 한다는 것을 의미한다.
우리는 userprog 디렉토리에서 작업할 것이다.
process.c, process.h
ELF binaries : 리눅스에서 실행 가능(Executable)하고 링크 가능(Linkable)한 file의 Format을 ELF(Executable and Linkable Format)라고 한다. 즉, 실행 가능한 바이너리 또는 오브젝트 파일 등의 형식을 규정한 것 !
syscall.c, syscall.h
유저 프로세스가 일부 커널 기능에 접근하려 할때마다 시스템 콜이 호출된다.
현재 상태에서는 단지 메세지를 출력하고 유저 프로세스를 종료시키게 되어있다.
syscall-entry.S
부트스트랩 프로그램 : 전원을 켜거나 재부팅을 할 때 적재되는 프로그램
exception.c, exception.h
응용프로그램이 시스템 콜을 호출하면 하드웨어는 '트랩 핸들러'를 실행하여 하드웨어 특권 수준을 커널모드로 격상시킨다.
커널모드에서 운영체제는 시스템 하드웨어를 자유롭게 접근할 수 있다.
gdt.c, gdt.h
segmentation 기법 : 프로그램을 논리적 의미 단위인 세그먼트의 집합으로 구성하는 방식
tss.c, tss.h
유저 프로세스가 인터럽트 핸들러에 진입할 때, 하드웨어는 TSS에게 커널의 스택 포인터를 찾아 달라고 요청한다.
pintOS에서 가상 메모리는 두 영역으로 나눌 수 있다
하나의 프로세스는 하나의 유저 가상 메모리는 갖는다. 프로세스 context switching이 일어날 때, 커널은 유저 가상 주소 공간 또한 바꿔준다. 스레드 구조체는 하나의 프로세스의 페이지 테이블을 가리키는 포인터를 가지고 있다.
pintOS에서 커널 가상 메모리는 물리 메모리와 일대일 대응으로 매핑되는데, 이는 KERN_BASE에서 시작한다. 즉, 가상 주소 KERN_BASE가 물리 메모리 0에 접근하고, 가상주소 KERN_BASE + 0x1234 가 물리주소 0x1234에 접근한다.
유저 프로그램은 자신의 유저 가상 메모리에만 접근할 수 있다. 만약 커널 가상 메모리에 접근하려 시도하면 page fault를 일으키고 프로세스는 종료된다.
반면, 커널 스레드는 커널 가상 메모리와 동작 중인 프로세스의 사용자 가상 메모리에도 접근 가능하다. 하지만 커널 안에서도 매핑되지 않은 주소에 접근하면 page fault를 일으킨다.