6. Mechanism: Limited Direct Execution

 

지난 포스팅에서 짧게 알아본 cpu 가상화는 time sharing에 의해 구현될 수 있었다.

이제 cpu 가상화의 구체적인 기법 또는 mechanism에 대해 알아보겠다.

 

 

우선 cpu 가상화를 하기 위해 해결해야 하는 문제가 있다.

1. 어떻게 시스템의 성능 저하 없이 (과도한 오버헤드를 추가하지 않고) 가상화를 구현할 수 있을까?

2. 동시에 프로세스를 여러개 time sharing을 해가며 실행시킬 때 운영체제가 어떻게 cpu에 대한 control을 유지할 수 있을까?

 


 

운영체제 개발자들은 프로그램을 빠르게 실행하기 위하여 제한적 직접 실행 Limited Direct Execution기법을 개발했다.

여기서 직접 실행 Direct Execution 은 운영체제가 프로그램을 cpu에서 직접 실행시키는 것을 의미한다.

위 설명의 1~6번까지는 프로그램이 프로세스가 되고 운영체제가 프로세스를 실행시키는 과정을 이야기하고 있고, 6번에서 운영체제가 프로그램의 main함수를 부르면 7~8번에서 main함수가 끝나기 전까지 아무런 제약 없이 main함수를 실행시키는 것을 볼 수 있다. 이것이 직접 실행의 원리이다.

더보기

위의 과정을 따라 프로그램이 실제로 실행될 때 1~6번의 운영체제에 어떤 일이 일어나는지 알아보자

1. 운영체제가 프로그램을 실행하면 프로세스를 만들기 위해 프로세스의 정보를 담을 수 있는 Process Control Block을 만든다. 이 PCB는 ready상태가 되어서 ready process list에 넣어준다. 
2, 3. 디스크에 있는 프로그램의 코드와 데이터를 메모리에 일정부분 할당하고 복사한다.
4. 메모리에 스택과 힙을 붙여주고 이 프로그램의 메인함수에 input parameter를 전달하기 위해 스택에 argc와 argv를 넣는다.
5. 각 레지스터를 초기화해준다.
6. 프로그램의 main함수를 호출한다.

 

이 과정에서 알 수 있는 사실 : Direct Execution에서 운영체제는 프로그램 실행 중 아무런 제어권을 가질 수 없다.

 

이는 곧 A란 프로그램과 B 프로그램을 동시에 실행시킬 수 없다는 의미를 갖는다. OS에서 A를 실행시키면 A가 끝난 후에야 OS가 제어권을 갖고 그제서야 B를 실행시킬 수 있다. ( OS > A > OS > B 순서로 제어권을 갖는다 )

만약 여기에서 이미 일정 공간 할당된 메모리 외에 추가적인 메모리를 필요로 하는 제한된 연산을 실행한다면 ( 예를들어 A 프로그램 실행 중 B 프로그램의 데이터를 갖고와서 덮어쓰는 명령어 등..) 시스템을 망가뜨릴 수 있기 때문에 우리는 protected control transfer 개념을 도입했다.

여기에 user mode와 kernel mode가 있다.

user mode는 하드웨어 자원에 제한적으로만 접근할 수 있는 application mode이고,  kernel mode는 하드웨어에 모든 접근이 가능한 운영체제가 사용하는 모드이다.

만약 user mode에서 파일을 읽고 써야 할 때는 어떻게 해야 할까? 이러한 경우를 대비해서 운영체제는 user program이 사용할 수 있도록 핵심적인 기능들을 System Call에 모아놨다. 이러한 시스템 콜들은 Application들이 정당한 요청인지 아닌지 판별 한다. Application이 restricted operation을 수행하려고 하면 시스템 콜을 수행하지 않고 바로 에러를 낸다.

 

정리하자면 user mode에서 실행되던 application이 하드웨어 자원에 접근할 수 없어서 시스템 콜을 호출하면 cpu의 모드는 user mode에서 kernel mode로 바뀌면서 시스템 콜이 수행되고 하드웨어에 접근하게 된다. 수행이 끝나면 그 결과를 application에 반환하고 kernel mode에서 user mode로 다시 바뀌면서 시스템 콜 이후의 코드를 수행한다.

 

 


 

 

시스템 콜을 구현할 수 있는 두 가지 명령어가 있다.

- trap instruction

application이 user mode에서 실행할 수 있는 명령.

더보기

user program에서 kernel의 아무 곳이나 jump할 수 있는 것이 아니라 kernel의 swi (software interupt) entry 안의 swi handler함수로 jump한다. 이렇게 vector address를 담고 있는 vector table로 jump할 때 privilege레벨이 user에서 kernel로 바뀐다. (각각의 이벤트에 따라서 trap table의 정해진 위치로만 jump한다)

- return from trap instruction

운영체제가 시스템콜의 수행을 마치고 실행하는 명령. kernel에서 user mode로 돌아간다. 

 

 

OS, HW, Program의 역할을 부팅과 실행으로 나눠서 본 프로세스 실행

컴퓨터가 부팅하면 운영체제는 trap table을 초기화한다. 하드웨어는 메모리에 vector table의 시작 주소를 알려준다. 그러면 cpu는 trap 명령어가 들어왔을 때 어느 위치로 가서 system call handler를 수행할 수 있을지 알 수 있다.

 

중요

운영체제가 실행중엔 일련의 프로세스 실행 과정을 수행하고 스택에 user stack과 kernel stack을 저장한다. (스택엔 지역, 매개변수, return address가 저장되어 있음) 이것은 기존 user mode 상태의 프로그램에 있었던 code, data, stack, heap이 kernel mode로 바뀌게 되면서 역할 또한 나뉜다.

user stack은 기존에 우리가 알던 stack의 역할인 운영체제의 함수를 수행할 때 필요한 input parameter, local variable, return address를 저장하는 역할을 한다.

 kernel stack은 user mode에서 kernel mode로 들어갈 때 유저모드 레지스터의 내용들을 저장하는 역할을, 반대로 커널에서 유저로 돌아갈 때 내용을 복원하는 역할을 한다. 이 때 cpu안의 kernel stack은 pc에 어디에서부터 다시 실행해야 하는지를 저장하여 kernel에서 user으로 돌아갈 때 pc의 주소를 참조한다.

아래는 위 설명의 연장선으로 함수의 실행부터 종료까지의 나머지를 설명한 것이다.