주제 | 세부 내용 |
Virtualization | CPU 가상화 |
메모리 가상화 | |
Concurrency | Thread |
Lock | |
Condition Variable | |
Semaphore | |
Deadlock | |
Persistence |
Limited Direct Execution
CPU를 가상화해야 하는 이유를 이전 글에서 알 수 있었다. 여러 개의 프로그램을 작동시키기 위해서 CPU 가상화가 필요했는데, 이는 Time Sharing 기법으로 실행할 수 있다. 그러나, 이러한 방법에 문제점이 있다. 첫 번째로 Performance이다. 시스템에서 가상화를 수행할 때 추가적인 오버헤드 없이 가상화를 실행하는 방법을 생각해야 한다. 두 번재는 Control이다. CPU에 대한 제어를 유지하면서 프로세스를 효율적으로 실행시키는 방법을 생각해야 한다. 여기에서 제어(Control)란, 접근 불가능한 리소스에 접근이 안되게 하는 등의 역할을 한다. 이번 글에서는 성능과 제어를 유지하면서 CPU를 가상화하는 방법에 대해 알아본다.
Direct Execution
Direct Execution이란 프로그램을 한 번 수행하면 종료될 때까지 수행하는 방법이다. Limited Direct Execution은 개발자들이 프로그램을 빠르게 실행하기 위해 만든 방법이다. 그러나 Direct Execution과 같은 방법은 CPU를 가상화할 수 없다. 한 번 실행된 프로세스에 대해 제어할 수 없고 Time Sharing을 할 수 없다. 따라서 제한(Limit)을 두어 프로세스를 관리해야 CPU를 가상화할 수 있다.
Problem #1 : Restricted Operation
Direct Execution은 빠르다는 장점이 있지만, 실행 중 디스크에 I/O 요청을 하거나 CPU나 메모리에 더 많은 자원을 요청하는 경우를 해결할 수 없다. 따라서 이를 해결한 방법이 필요하다.
첫 번째 방법은 프로세스가 I/O 및 기타 작업들을 수행하도록 하는 것이다. 그러나 파일에 대한 접근 권한을 주기 전에 권한을 확인하려는 파일 시스템을 만든다고 가정할 때, 프로세스가 디스크에 대한 I/O 요청을 처리할 수 있도록 설정해도 권한을 얻을 수 없다. 만약에 권한을 얻는다면, 중요한 데이터를 잃을 수도 있다.
대부분의 명령은 직접적으로 실행될 수 있으며 가끔은 간접적으로 실행되어야 한다. 따라서 이러한 문제를 해결할 방법이 User Mode와 Kernel Mode로 상태를 구분하는 것이다. User Mode에서는 수행할 수 있는 작업을 제한해서 I/O 요청과 같은 제한된 작업을 하려고 하는 경우, 예외를 발생시키고 OS를 중단한다. 이를 보완할 수 있는 것이 Kernel Mode이다. Kernel Mode에서는 I/O 요청과 같은 권한이 필요한 작업(Privileged operations)을 수행할 수 있다.
만약 프로그램이 제한된 작업을 수행하려면 어떻게 해야 할까? 하드웨어는 System Call을 수행할 수 있도록 제공하고 있다. System Call은 프로그램에 파일 시스템에 접근하거나 더 많은 메모리를 할당하는 것과 같은 기능을 할 수 있도록 한다. System Call이 실행되면, 프로그램은 Trap 명령을 발생시켜 Kernel Mode로 들어가게 하고, 수행이 완료되면 return-from-trap이라는 명령을 통해 다시 돌아온다.
Trap 명령이 사용되면 OS는 Kernel Stack이라는 곳에 Program Counter, flag, register를 저장한다. return-from-trap 명령이 사용되면, 이 값들을 빼고, User Mode의 프로그램을 제개한다.
User Mode에서 Kernel Mode로 switch 할 때 System Call을 사용한다는 것을 알았다. 그렇다면 OS에서는 Trap을 어떻게 사용할까? Trap을 처리하기 위해서 OS는 Trap Table이라는 것을 사용한다. 이는 시스템이 부팅될 때 초기화되어 세팅되며 OS는 CPU에 Trap handler의 위치를 알려준다. 각 System Call에는 system-call number이라는 것이 지정되어 있는데, OS는 이 숫자를 보면서 유효한지 판단하고 코드를 실행시킨다. 또한 trap table의 위치를 알리는 것은 privileged operation에 의해 이루어지는 것이다.
참고로, OS는 어디에 위치하는 것일까?
바로 User Process 의 같은 주소상에 위치한다. Mode를 Switch할 때마다 User Process 내부의 OS Kernel을 실행한다. 즉, User Mode, Kernel Mode 간 Switching이 같은 프로세스 안에서 일어난다는 것이다.
아래 그림은 System Call의 과정을 나타낸 것이다.
Problem #2 : Switching between Processes
지금까지는 한 프로세스 내에서 권한이 필요한 작업을 수행하는 경우에 대해 알아봤다면, 지금부터는 두 프로세스를 동시에 수행하는 경우 발생할 수 있는 문제에 대해 알아볼 것이다.
우리는 이전에 Time Sharing 기법으로 한 프로세스에서 한 프로세스로 전환한다고 배웠다. 이는 CPU의 제어권을 가져와서 어떤 프로세스를 실행할지를 결정하는 것이다. 만약 CPU에 프로세스가 동작하고 있다면 OS는 동작하지 않는다. OS가 CPU의 제어권을 얻을 수 있는 방법은 뭘까? 첫 번째로 System Call이 발생하면 대기(wait)하는 것이다. 프로세스는 주기적으로 CPU의 제어권을 포기하기 때문에 OS가 제어권을 얻어 어떤 프로세스를 실행시킬지 결정한다. 만약에 OS에 제어권이 오지 않는다면 무한 루프를 돌게 된다. 이를 해결하는 두 번째 방법이 Timer Interrupt이다. 이는 timer가 끝나면 Interrupt를 발생시켜 제어권을 넘기는 방법이다.
이때, Interrupt란 무엇일까? 간단하게 말하면, Trap은 소프트웨어적인 사건이고 Interrupt는 하드웨어적인 사건이다. (이 둘의 차이에 대한 자세한 사항은 이곳을 참고하면 된다.) Interrupt를 처리하는 방법은 Trap과 유사하다. Interrupt Table에 Interrupt를 처리하는 Interrupt Handler가 존재하며 이를 사용해 Interrupt를 제어한다. 예를 들어, 10ms동안 프로그램을 실행하고 다른 프로그램을 실행하려고 하는데 timer Interrupt가 1ms 마다 발생한다고 가정한다. 그러면 10번의 Timer Interrupt가 발생하고 OS가 제어권을 갖고 다른 프로그램을 실행시킬 수 있다.
그렇다면, 실행되는 프로세스가 바뀔 때 OS에게 제어권을 넘겨주는 방법도 있다. 이것이 바로 Context Switching이다. 만약 프로세스 A, B가 존재할 때, A에서 B로 넘어가고 다시 A로 넘어올 때 처음부터 실행되는 것과 중단된 이후부터 실행되는 것 중에 무엇이 더 효율적일까? 후자가 훨씬 효율적이다. 이를 Context Switching이라 한다. 이는 곧 실행될 프로세스를 위해서 현재 프로세스의 레지스터 값을 메모리에 저장하는 방식이다.
Worried about Concurrency?
하나의 Interrupt를 처리하는 도중에 다른 Interrupt가 발생하는 경우 무엇을 먼저 처리해야 할 지, System Call과 Timer Interrupt가 발생하면 무엇을 먼저 처리해야 할 지에 대한 문제는 여전히 존재한다. OS는 Interrupt를 Disable 하거나 Shemes를 Lock하는 방법도 존재한다.
'CS > 운영체제' 카테고리의 다른 글
[OS] 1. 프로세스란 무엇인가? (0) | 2024.03.08 |
---|