티스토리 뷰
[OS] Limited Direct Execution 메커니즘이란? - OS 공부 2
Dev_Pingu 2020. 8. 22. 14:04안녕하세요! Pingu입니다~
이번 글에서는 운영체제에서 Process라고 불리는 것에 대해 알아보려고 합니다. 제가 공부할 때 참고하고 있는 OSTEP 책에선Chapter 6 - Direct Execution부분입니다.
Limited Direct Execution
CPU를 가상화해야 하는 이유는 저번 글에서 알아봤습니다. 간단히 말하면 여러 개의 프로그램을 동시에 작동하기 위해 CPU 가상화가 필요했는데요, 이는 실제로는 Time Sharing
기법으로 구현할 수 있었습니다. Time Sharing
을 사용하여 CPU 가상화를 구현하려면 몇 가지 고려해야 할 점이 있습니다. 첫 번째는 Performance
입니다. 시스템에서 가상화를 구현할 때 오버헤드 없이 구현하는 방법을 생각해야 합니다. 두 번째는 Control
입니다. CPU에 대한 제어를 유지하면서 프로세스를 효율적으로 실행하는 방법을 생각해야 합니다. 여기서 제어란 접근 불가능한 리소스에 접근이 안되게 하는 등의 역할을 합니다. 즉 이번 글에서는 성능과 제어를 유지하면서 CPU 가상화를 구현하는 방법을 알아보려고 합니다.
Basic Technique: Limited Direct Execution
개발자들은 프로그램을 빠르게 실행되도록 하기 위해 Limited Direct Execution
이라는 기술을 만들었습니다. 여기서 Limit
를 뺀 Direct Execution
은 프로그램을 한 번 수행하면 종료될 때까지 수행하는 방법입니다.
위의 표와 같이 한 번 실행하면 종료될 때까지 프로세스는 멈추지 않습니다. 하지만 이 방법으로는 지금 구현하려고 하는 CPU 가상화를 구현할 수 없습니다. 우선 한 번 실행된 프로세스에 대해 제어를 할 수 없으며 Time Sharing
을 할 수 없습니다. 즉 이러한 방법에 어떠한 Limit
를 줘야 CPU 가상화를 구현할 수 있게 됩니다! 그럼 이를 해결하기 위한 Limit
를 살펴보도록 하겠습니다.
Problem #1: Restricted Operations
아까 본 문제점이 있던 Direct Execution
은 빠르다는 장점은 있습니다. 하지만 실행 중 디스크에 대한 I/O 요청이나 CPU, Memory에서 더 많은 리소스를 요청하는 경우를 해결할 수 없기 때문에 사용할 수 없었습니다. 이를 해결하기 위한 방법에는 어떤 방법이 있을까요?
첫 번째 방법은 프로세스가 I/O 및 기타 작업들을 모두 수행하도록 하는 것입니다. 하지만 이렇게 하는 것은 바람직하지 못할 수 있는데, 예를 들어 파일에 대한 접근 권한을 부여하기 전에 권한을 확인하려고 하는 파일 시스템을 만든다고 생각해보겠습니다. 이때 프로세스가 디스크에 대한 I/O를 처리하게 설정해도 권한을 부여할 수는 없습니다. 만약 이를 허용한다면 프로세스가 디스크를 마음대로 접근할 수 있기 때문에 보호 기능이 손실되게 됩니다.
이러한 문제 때문에 실제 사용되는 방법은 프로세스를 User mode
, Kernel mode
로 상태를 구분하는 것입니다. User mode
상태에서는 수행할 수 있는 작업에 제한을 둬서 해당 작업을 수행하려고 하면 오류를 발생합니다. 이를 보완하기 위해 Kernel mode
라는 OS가 실행되는 상태를 만들었고 I/O 요청과 같은 권한이 필요한 작업은 Kernel mode
상태에서 수행하게 됩니다.
하지만 만약 User mode
의 프로세스가 Kernel mode
에서 수행 가능한 작업을 원할 땐 어떻게 해야할까요? 이럴 때 사용하는게 system call
입니다. System call
은 user mode
프로세스에게 kernel mode
에서 수행가능한 작업을 수행할 수 있게 해 줍니다. System call
이 실행되면 trap
명령으로 권한을 바꿔 작업을 수행하고 수행 후엔 OS가 return-from-trap
명령으로 다시 원래의 권한으로 돌아옵니다.
Trap
명령이 수행되면 프로세스는 program counter, flags, register 정보를 kernel stack
에 넣습니다. 그런 뒤 return-from-trap
명령이 수행되면 이러한 데이터를 모두 제거합니다.
이제 user mode
에서 kernel mode
로 mode switch
할 때 trap
을 사용한다는 것도 알았습니다. 그렇다면 OS는 trap
을 어떻게 사용할 수 있을까요? OS가 trap
을 처리하기 위해선 위의 그림과 같은trap table
이라는 것을 사용합니다. 이는 부팅할 때 초기화가 됩니다. Trap table
에는 소프트웨어적 사건들을 처리하기 위한 함수가 들어있습니다. 또한 이러한 함수들에는 system-call number
이라는 번호가 정의되어있고 위의 그림의 테이블을 사용한다고 가정했을 때, divide_by_zero()
함수를 호출하고 싶다면 0
을 전달하게 됩니다. 그럼 실제 프로세스가 trap을 사용하여 작업을 수행하는 과정을 살펴보겠습니다.
위와 그림과 같이 진행되며 trap table
은 부팅할 때 OS가 생성합니다. 그 이후 프로세스가 생성되어 user mode
에서 수행하다 system call
이 발생하여 trap
으로 kernal mode
로 접근합니다. 해당 작업이 끝나면 다시 user mode
로 돌아와 작업을 수행하고 작업이 끝나면 프로세스를 제거하게 됩니다.
Problem #2 Switching Between Processes
지금까지 알아본 Limited Direct Execution
으로 하나의 프로세스가 수행되다 권한이 있는 작업을 수행하는 방법에 대해 알아봤습니다. 그렇다면 이젠 하나의 프로세스가 아닌 여러 개의 프로세스를 동시에 실행할 때 발생할 수 있는 문제를 해결하기 위한 방법을 알아보겠습니다!
CPU 가상화를 위한 방법으로 Time sharing
방법이 있다고 했었습니다. 이 방법은 실제로 여러개의 프로세스가 동시에 실행되는 것이 아닌 사람은 느낄 수 없는 아주 짧은 시간 동안 프로세스들을 실행하여 마치 동시에 실행되고 있는 것처럼 보이게 하는 방법이었습니다.
위와 같이 time sharing
기법을 사용하여 프로세스들을 진행할 때 실행할 프로세스를 바꿀 때 OS가 제어권을 가져와 서 어떤 프로세스를 다음에 실행할지와 같은 부분을 제어해줘야 합니다. 이렇게 OS가 제어권을 가져오는 방법에는 2가지 방법이 있습니다. 첫 번째는 서로 협력하는 방법으로 system call
을 사용하는 방법입니다. 프로세스가 system call
을 발생하면 OS로 제어권이 넘어오게 되고 OS는 스케쥴링과 같은 작업을 수행 후 다음 프로세스에게 제어를 넘기면 됩니다. 하지만 이 방법은 만약 어떤 프로세스가 system call
을 발생하지 않는다면 어떻게 될까요? 아마 OS에게 제어가 넘어오지 않는 상황이 발생할 수도 있을 것 같습니다. 이를 해결하기 위한 두 번째 방법은 time interrupt
를 사용하는 것입니다.
자, 그럼 interrupt
는 무엇일까요? 아까 trap
은 소프트웨어적 사건이라고 했는데 interrupt
는 하드웨어적 사건을 OS에게 알리는 메커니즘이라고 볼 수 있습니다. Interrupt
를 처리하는 방법은 trap
을 처리하는 방법과 유사합니다. Interrupt table
에 다양한 interrupt
를 처리하는 interrupt handler
가 정의되어있고 이를 사용해 처리하게 됩니다. 그럼 아까 두 번째 방법으로 사용한다던 time interrupt
를 알아보도록 하겠습니다. Time Interrupt
는 일정 시간마다 interrupt
를 발생시키는 방법입니다. 예를 들어 10ms동안 프로그램을 실행하고 다음 프로그램을 진행하려고 하는데 time interrupt
는 1ms마다 발생한다고 가정해보겠습니다. 그럼 10번의 time interrupt
가 발생되면 OS가 제어를 갖고 다음 프로세스를 실행하는 아주 간단한 아이디어입니다.
그럼 이제 실행되는 프로세스가 바뀔 때 OS에게 제어를 주는 방법도 알았습니다. 그럼 여러 개의 프로세스를 잘 수행할 수 있을까요? 아쉽게도 아직은 아닙니다. 아직 남은 문제점이 무엇인지 살펴보겠습니다!
만약 A, B 프로세스가 있다고 가정합니다. Time sharing
기법으로 두 개의 프로세스를 번갈아 가며 실행하는데 A 프로세스를 실행하다 B 프로세스가 실행되고 다시 A 프로세스를 실행하려고 하는 경우 다시 처음부터 실행하는 것이 효율적일까요? 아니면 진행한 부분은 생략하고 그 이후부터 실행하는 것이 효율적일까요? 당연히 후자가 효율적입니다. 이렇게 프로세스의 정보를 기억했다 나중에 다시 실행될 때 사용하는 방법을 context switch
라고 합니다. 여기서 context
란 나중에 다시 실행될 때 사용될 프로세스에 대한 정보이고 하드웨어 register
의 집합입니다.
Context switch
는 context save
, context restore
라는 두 가지 작업으로 구성됩니다. 작업의 이름을 보면 바로 이해할 수 있듯이 하나는 context
를 저장하는 것이고 하나는 복구하는 것입니다. Context save
는 프로세스가 진행되다 다른 프로세스를 진행할 때 나중에 다시 실행되기 위해 정보를 저장하는 것이고 context restore
는 프로세스가 다시 실행될 때 저장한 프로세스에 대한 정보로 복구하는 작업입니다. 참고로Context save
는 Process Control Block
이라는 구조로 저장되게 됩니다.
위의 그림은 time interrupt
기법을 적용한 프로세스 실행 과정입니다. 이 과정에서 부팅 시 interrupt table
과 trap table
을 trap table
로 한 번에 처리하였고 time interrupt
를 위한 interrupt timer
를 실행해줍니다. A 프로세스가 실행되다 timer interrupt
가 발생하여 레지스터에 context
를 저장하고 프로세스 B의 context
를 복구한 뒤 프로세스 B를 실행하게 됩니다. 물론 이렇게 진행되면 아주 복잡해 보이지만 아주 짧은 시간에 수행되기 때문에 사용자는 마치 두 개의 프로세스가 동시에 실행 중인 것처럼 보이게 됩니다.
어느 정도 이해가 되셨나요?? 저는 잘 이해가 안 되어 context switch
진행과정을 그림으로 그려봤습니다. 그림이 도움이 될까 해서 올려보겠습니다 ^~^
위와 같은 방식으로 진행되는 context switch
도 시간이 걸리며 오버헤드가 발생하는 작업입니다. 그래서 하드웨어에서 context switch
를 지원하는 hyper-threading
라는 기술도 존재합니다.
위의 코드는 Context Switch
가 수행되는 수도 코드를 나타낸 것입니다. 복잡해 보이지만 알고 보면 정말 간단한데요, 우선 코드가 Save
, Load
로 크게 나눠져 있습니다. Save
는 CPU에 있는 데이터를 메모리로 옮기는 작업이고 Load
는 메모리에 있는 데이터를 CPU로 옮기는 작업입니다. 아주 간단하죠?
Worried About Concurrency?
지금까지 CPU 가상화를 하기 위해 프로세스에서 발생하는 문제와 해결방법을 알아봤습니다. 근데 또 문제가 있을 수 있습니다. 문제가 계속 발생하네요 ㅠ.ㅠ 어쨌든 발생할 수 있는 문제는 하나의 interrupt
를 처리 중에 다른 interrupt
가 발생하면 누구를 먼저 처리할 지에 대한 문제, system call
을 처리중 timer interrupt
가 발생하면 어떤 것을 먼저 처리할지에 관한 문제가 되겠습니다.
이런 문제를 해결하는 방법에는 다음과 같은 방법이 있습니다.
- Disable interrupt
- 다른 인터럽트 처리 중일 때 발생하는 인터럽트는 무시하는 것이다.
- Priority
- interrupt에 우선순위를 줘서 순차적으로 처리한다.
- Locking mechanism
- Lock 기법을 사용하여 처리한다.
이러한 문제는 Concurrency
단원에서 다시 다뤄보도록 하겠습니다!
마무리
이번 글에서는 Limited Direct Execution
에 대해서 알아봤습니다. 직접 수행을 하는 것을 허용하지만 발생하는 문제를 처리하는 방법을 알아봤습니다. 프로세스가 권한이 있는 작업을 수행하고 싶을 때를 해결해주는 Mode switch
, 프로세스들이 time sharing
기법으로 실행될 때 프로세스의 정보를 기억하기 위한 context switch
가 있었습니다!
읽어주셔서 감사합니다!
다음 글 : 프로세스를 스케줄링 하는 방법들
'Computer > Operating System' 카테고리의 다른 글
[OS] 공평한 스케줄러 만드는 법 (Proportional Share) - OS 공부 5 (4) | 2020.10.18 |
---|---|
[OS] MLFQ(Multi Level Feedback Queue) 스케줄링 방법 - OS 공부 4 (5) | 2020.10.17 |
[OS] 프로세스를 스케줄링 하는 방법들 (Scheduling) - OS 공부 3 (0) | 2020.10.16 |
[OS] 운영체제에서 Process란? - OS 공부 1 (1) | 2020.08.12 |
[OS] OSTEP으로 운영체제 공부시작 - OS 공부 0 (0) | 2020.08.11 |
- Total
- Today
- Yesterday
- Xcode
- 코테
- System
- dfs
- 알고리즘
- 백준
- OSTEP
- Swift
- IOS
- design
- operator
- Apple
- Publisher
- 앱개발
- BFS
- Combine
- pattern
- 동시성
- operating
- 테이블뷰
- 자료구조
- 아이폰
- 코딩테스트
- mac
- 스위프트
- OS
- document
- DP
- 문법
- 프로그래밍
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |