os는 cpu, disk, memory를 가상화하는 역할을 한다.
cpu 가상화는 물리적으로 제한된 cpu를 무수히 많은 것처럼 보이게 하여 각 프로세스마다 각자의 cpu를 가진 것처럼 보이게 한다.
os는 시간을 일정한 time quantum으로 나누고, time quantom마다 process가 번갈아가며서 cpu를 사용할 수 있게 한다
오직 하나의 process만 cpu를 사용한다고 해보자.
1. code, data를 메모리에 할당한다.
2. stack 영역을 할당한다.
3. heap 영역을 할당한다.
4. file descriptor table을 초기화한다.
5. entry point를 찾아 프로그램을 실행한다.
6. 프로그램이 종료한다.
7. 할당된 메모리를 해제한다.
위와 같은 과정에 의해 process가 실행될 것이다. cpu 주도권을 해당 process가 쭉 가져가는 것이다.
❕ 이때 발생하는 문제가 있다.
위의 direct execution은 빠르기는 하지만, 여러 가지 문제가 있다.
이에 대한 해결책으로, os는 두 가지 mode로 나눈다.
즉, process가 hw에 접근하고 싶으면, kernel mode로 바뀌어 os가 대신 해준다는 것이다.
그럼 어떻게 hw에 접근하고 싶다고 표현하느냐? 이게 바로 system call이다.
system call은 os가 HW에 접근하는 방법을 제공한다.
system call을 통해
system call을 호출하여 user mode에서 kernel mode로 바뀐다고 하였다. 이를 가능하게 해주는 것이 trap instruction이다.
int n
과 같은 형태로 n번 trap을 걸어줌으로써, n번에 해당하는 trap handler가 실행돼서 kernel mode로 넘어가게 된다.
trap으로 kernel mode로 넘어간 후에는 return from trap instruction으로 다시 usermode로 돌아가게 된다.
user program이 systemcall을 호출하면, trap이 걸려서 trap table에서 해당 handler의 주소를 찾고 handler를 실행하게 된다. 그럼 trap table에서 handler를 찾으려면 먼저, trap table이 메모리에 어디에 저장돼있는지를 알아야 한다.
즉, cpu는 trap table의 주소를 알아야한다.
HOW ? -> os가 부팅할때 trap table을 초기화하고, cpu에게 각 trap handler의 주소를 알려준다.
위와 같이 user mode, kernel mode 두 가지로 나누고, system call을 호출하고 trap을 걸어 kernel mode로 넘어가서 hardware resoure에 접근하도록 하였다.
hardware 접근 문제는 해결했는데, process에서 process로 cpu의 컨트롤이 어떻게 넘어갈것인가 하는 문제는 아직 해결하지 못했다.
이에 대한 해결책으로 두가지가 제시된다.
1. 각 process가 yield systemcall을 호출하여 다른 프로세스에게 cpu 주도권을 넘긴다.
2. os가 cpu 주도권을 중재한다.
1번 해결책은 문제가 있다. 한 프로세스가 yield를 호출하기 전에 무한루프를 돌면? 절대 cpu 주도권이 안 넘어오고 계속 그 process만 돌아가기 때문엔 결국에 시스템을 재부팅해야한다.
따라서 2번 해결책이 더 그럴듯하다. os가 timer interrupt를 걸어서 cpu 주도권을 다른 process에게 주는 것이다.
프로세스 실행 중 timer interrupt가 걸리면 레지스터 값을 kernel 스택에 저장한다. 그리고 다음 실행될 프로세스의 레지스터값을 kernel 스택에서 가져와서 레지스터에 담고, 그 kernel 스택으로 전환한다.