3 little things- Limited Direct Execution 정리+ 번역
Computer Science/Operating system

3 little things- Limited Direct Execution 정리+ 번역

 

https://yongy0ng2.tistory.com/47

 

06 Direct Execution

운영체제가 어떤 프로그램을 실행시키는 가장 간단한 방법은, 이를 직접 실행시키는 것이다. 프로세스에 메모리를 할당하고 프로그램 코드를 디스크에 탑재하여 CPU 상에서 그대로 실행시킴을 의미하는데, 이렇게..

yongy0ng2.tistory.com

https://satisfactoryplace.tistory.com/50

 

[Operation Systems] Limited Direct Execution

왜 Limited 되어야 하는가? Limited되지 않는다면, OS와 Program은 동등한 계층(hierarchy)를 갖는다. 따라서 OS는 Program을 감시하거나 동작을 제어할 수 없다. 만약 Program이 무한히 돌고 있다면(intended하든..

satisfactoryplace.tistory.com

위 두 포스트 참고하여 작성하였습니다.

1. CPU virutalization issue

 : CPU virtualization을 하기 위해, OS는 맣은 작업들이 동시에 이뤄지고 있는 physical CPU를 공유해야 한다.

 => 하나 프로세스 잠깐, 그리고 다음 프로세스 잠깐, 다음프로세스 잠깐... 이렇게 time sharing을 하면서 CPU virtualization이 이뤄지게 된다.

 

  <이때 발생하는 몇가지 issue가 있음>

  1) Performance 

: 우리는 과도한 overhead를 발생시키지 않고 virtualization이 가능한가?

   

  2) Control

: 우리는 어떻게 CPU를 통제하면서 프로세스를 효율적으로 운용이 가능한가?

  Control은 상당히 중요하다, 통제 없이는 프로세스가 영원히 돌아갈것이고, 기계 전부를 잡아먹을 것이다. 또는 정보에 접근하는 게 허용되지 않을 수 있다.

=> Obtaining High performance while maintaing control is on of the central challenges in building an operating system.

 

# OS는 CPU를 효율적으로 가상화하면서 동시에 system을 control할수 있어야 한다. 이를 위해서는 OS와 hardward 사이의 협력이 필요하다. OS는 이를 위해 하드웨어의 judicious한 부분을 가끔 사용한다.

 

 

2. Basic Technique : Limited Direct Execution

: 프로그램을 기대한만큼 빠르게 동작시키기 위해 os developer들을 limited direct execution이라는 시스템을 도입했다.

-> 이 direct execution이라는 개념은 CPU에 프로그램을 직접적으로 돌리는 것이다.  OS가 프로그램이 동작하기를 원할때, 이는 process list에 process entry를 생성하고, 그것을 위한 메모리를 할당하고, 프로그램 코드를 메모리에 적재하고, entry point에 프로그램을 위치시키며( ex. main() routine or sth), 사용자의 코드를 실행시키기 시작한다.

 

프로그램이 따로 실행되며, return을 실행시키면 다시 OS로 돌아와서 프로세스의 메모리를 해제하고, 프로세스 리스트에서 이를 제거한다.

 

But this approach gives rise to a few problem;;

-> 이 접근은 약간의 문제가 생길 수 있다.

  1.  프로그램이 실행되면서, 어떻게 프로그램이 효율적으로 작동하면서 우리가 원하지 않은 것까지 실행하지 않는지(doesn't do anything we don't want it  to do)까지 OS가 알수가 없다. 

  2.  프로세스를 실행하면서, 어떻게 OS가 프로세스를 멈추고, 다른 프로세스로 교체하면서 CPU virtualization을 위한  time sharing을 실행하게 되는가? 

 

-> 여기서 'Limited'라는 용어가 어디서 튀어나왔는지 알수 있게 된다. 이러한 제한 없이 OS는 아무것도 통제할수 없고 그저 library일 뿐이게 된다.

 

 

 


3. Problem #1: Restricted Operation (프로세스에 의한 원치 않는 코드의 실행 막기)

: direct execution은 확실히 빠르다는 장점이 있다. 프로그램이 hardware CPU에서 바로 동작하고, 또한 기대한만큼 빠르게 실행되기 때문이다. 하지만 CPU에 직접 동작하는 것은 문제가 있다. 

=> 프로세스가 제한된 operation을 실행하고 싶어할수가 있다. ( disk I/O를 실행하고 싶어할 수도 있고, 더 많은 시스템 resource( CPU or memory)에 접근하고 싶어할 수가 있다. (wants to gain access)

 

 # The Crux: How to perform restricted operations?

 : 프로세스는 I/O를 실행할 수도 있어야 하고, 다른 restricted operation을 실행할수도 있어야 한다

  -> without giving complete control over the system!! (important)

 

=> 이럴때 아무 프로세스든 간에 원하는 I/O나 operation을 모두 실행할 수 있게 해주는 방법도 문제를 해결하는 하나의 방법이다. 그렇지만 이 방법은 바람직 하지 않다. 예를 들어 파일 시스템 하나를 구축할때 권한을 체크하게 되는데, 이때 모든 프로세스가 I/O를 하도록 허용해버리면 이 프로세스가 모든 디스크를 읽어버릴 것이고, 디스크에 대한 모든 보호는 소용이 없어지게 된다.

=> 따라서 OS가 모든 프로세스의 최상위 계층에 위치해서 나머지 프로세스를 제어할 수 있어야 한다.

 

# 이를 해결하기 위해 Dual mode를 도입하게 된다!!!

 

1. User Mode: 제한된(restricted) 동작만을 할 수 있으며, kernel 모드에 진입해야 할 경우에는 system call을 이용해야 한다. 그렇지 않을 경우 OS는 Exception을 발생시켜 Process를 Kill한다.

 

2. Kernel Mode: OS가 동작하는 Mode이다.

Privileged Operation(ex- I/O request)을 포함하여 모든 동작을 제한받지 않고 수행할 수 있는 Mode.



특징 1) 이때, User mode일때는 Privileged instruction을 실행하면 안된다. 

OS는 user program을 전혀 신뢰하지 않는다. 프로그램을 짜면 버그가 발생하기 마련이고, 이러한 버그가 컴퓨터 시스템에 악영향을 끼칠수 있기 때문이다. 따라서 통제된 시스템 하에서만 User program이 실행된다.

 

특징 2) User mode에서는 application이 하드웨어 리소스에 full access 권한이 없고, Kernel mode에서는 full resource에 access가 가능하다. Trap instruction과 retrun-from-trap back to user mode 라는 instruction이 제공되고, 어디에 user program의 맥락을 저장해놓았는지를 알수 있는 trap table도 사용 가능하다. 

 

=> dual mode를 실행하면서 user mode 에서 kernel mode로 진입하기 위해 system call이라는 것을 호출하게 되는데, 이를 위해 잠시 user program을 멈추고 context를 저장한 다음에, interrupt를 처리하고, 그 후에  return-from-trap instruction을 통해 context를 복원하게 된다.

 

 

 # trap을 실행하면서 주의점이 몇 가지 발생한다.

1. 문맥을 저장해뒀던 위치에 다시 정확하게 돌아와야 한다. 이를 위해 kernel-stack에 counter, flag, register 등을 저장해두고, return-from-trap instruction이 실행되면 이를 pop 하게 된다.

 

2. 만약 프로그램이 커널의 특정 부분으로 실행 흐름을 jump할 수 있다면 임의의 코드를 실행할 수 있어 위험하다.

따라서 OS는 부팅 시에 trap table을 만들고, 하드웨어가 필요로 하는 trap 핸들러의 위치를 알려준다. 하드웨어는 이 정보를 이용해서 특정 작업(어떤 code 로 jump할지 등을 알수 있음)을 수행 할 수 있다.

 

=> 각각의 시스템 콜에는 system call number를 부여하여 각각을 구별할 수 있게 한다.

 

User/Kernel mode가 어떻게 작동하는지 자세하게 보여준다.

 

=> LDE는 두가지 phase를 통해 이루어진다.

  1. 먼저 kernel이 트랩 테이블을 초기화하고, CPU가 나중을 위해서 그 위치를 저장한다. (previleged instruction을 통해 실행되는 부분이다)

  2. 그 후에는 Return-from-trap instruction이 실행되기 전에는 Kernel이 메모리를 할당하는 등의 몇가지 준비를 한다. RFT가 실행되면 다시 CPU를 user mode로 전환하고, 프로세스를 실행하기 시작한다. (Waiting-> Running state로 돌아옴) : 다시 system call을 호출하고 싶으면, 다시 Trap을 하면 된다.

 

# 프로세스가 다 종료된 후에는 exit() system call을 호출하게되고, 이때 OS가 모든것을 지우고, 끝나게 된다.

 

 


#2. 프로세스 간의 전환 방법 (Switching Between Processes)

 -> 다음으로 발생할 수 있는 문제는 프로세스 간에 전환이 가능한지이다. 프로세스가 CPU에서 돌아가는 동안 OS는 running 상태가 아니라고 할 수 있다. CPU가 OS에서 돌아가지 않는다면, 어떻게 프로세스를 전환할 수 있을까?

 

1. Cooperative approach: Wait for System calls

이는 과거의 시스템에서 주로 채택되었던 방식으로, 프로세스가 system call을 호출하여 CPU를 제어하는 권한이 OS에게 돌아올때 까지 기다리고 있는 방식이다. 너무 오래 동안 돌아가는 프로세스는 CPU를 포기하고 OS가 다른 프로세스를 실행할수 있게 해준다.

=> 이러한 유형의 OS에서는 yield라는 system call을 제공하게 되는데, 이 system call은 단순히 제어권을 OS에게 돌려줘서  OS가 다른 프로세스를 실행할 수 있게 한다.

=> 또한 프로그램 접근 권한이 없는 곳에 접근을 시도한다거나, 어떤 값을 0으로 나누려 시도하는 등의 오류를 발생시키면 trap이 실행되어 OS가 제어권을 가지게 된다.

 

 

2. Non- Cooperative approach :The OS Takes Control

=> 위에서 설명한 cooperative apporach를 이용하면 무한루프에서 빠져나오지 못할때, 제어권이 영원히 OS에게 넘어오지 못할 수 있는 문제가 발생할 수 있다. 이를 보완하기 위해서 Non-cooperative 방식에서는 OS에게 항상 제어권이 넘어오도록 설계가 되어 있다.  (꼭 Reboot하지 않아도 되게!)

 

- 주로 사용하는 방법은 Timer Interrupt 방식을 이용하는 것이다.

이 장치는 정해진 millisecond마다 진행중인 프로세스를 중단시키고, 미리 구성된 OS의 interrupt handler가 실행된다. in이러한 방식으로 OS는 다시 제어권을 얻게 되고 원하는 일을 수행한다. 현재의 프로세스를 계속 실행시키거나, 다른 프로세스를 실행 시킬 수도 있다.

 

=> 이전에 언급했듯이, 하드웨어는 interrupt가 발생했을 때 실행되어야 할 코드를 정확히 알고 있어야 하며, OS는 타이머를 반드시 시작해서, 제어권이 OS에게 넘어왔을 때 프로그램을 실행할 수 있도록 해야 한다. 

또한, 이후에 Return- from - trap 명령어에 의해 프로그램이 정상적으로 다시 작동할 수 있도록 interrupt가 발생했을 때 프로그램의 레지스터값 등의 상태를 저장해두어야 한다.

 

 


#3. Context의 저장과 복원

OS가 어느 프로세스를 어떻게, 얼마나 실행 시킬 것인지는 scheduler라는 부분에 의해 결정된다. OS는 프로세스의 전환이 일어날 때 다음과 같은 context switch 코드를 실행한다.

 

=> 먼저, 이미 실행 중이던 프로세스의 레지스터를 커널 스택과 같은 곳에 저장하고, 앞으로 실행할 프로세스의 레지스터 값을 이미 저장해 놓은 값을 통해 복원하게 된다. 자세한것은 표로 확인할 수 있다.

 

=> OS가 process A에서 process B로 context switch 하려 한다고 가정해 보자.

1. Timer Interrupt 발생 (Hardware)

2. register(A) 정보를 Kernel Stack(A)에 저장 (Hardware)

3. Kernel Mode로 이동하고 trap Handler로 Jump한다 (Hardware)

4. Handle the trap 하고 switching 실행 (Kernel Mode)

5. register(A)정보를 proc-struct(A)에 저장 (Kernel Mode)

   register(B)정보를 proc-struct(B)로 부터 복구 (Kernel Mode)

   Kernel stack(B)로 Kernel switch (Kernel Mode)

6. return-from-trap(B) (Kernel Mode)

7. register(B)정보를 Kernel Stack(B)로부터 복구 (Hardware)

8. User Mode로 이동하고 B의 Program Counter가 가리키는 곳으로 이동 (Hardware)

9. Process B 실행


=> 이때 Timer interrupt에 의해 제어권을 OS에게 넘겨주기 위해 하드웨어가 프로세스의 레지스터값을 커널 스택에 저장하는 것과, Process switching을 위해 OS가 프로세스의 레지스터 값을 프로세스 구조체에 저장하는 것의 차이를 기억해야 할 것이다! ( 두 타입의 레지스터 저장은 다른 것이다.)

Process A의 레지스터를 구조체에 저장한 뒤, B 구조체로부터 레지스터를 복원해오면 OS가 A로부터 trap된 것에서 B로부터 커널로 trap된 것 처럼 시스템을 이동하게 된다.

 

=> old와 new는 각각의 프로세스 구조체 안에 있는 context 구조체이다.

 

 

 

#4. How about concurrency?

다른 interrupt를 처리하고 있는 중간에 다른 interrupt가 발생한다면?

system call을 처리하고 있을 때 timer interrupt가 발생한다면?

과 같은 문제를 제기할 수 있다.

 

이러한 내용을 다루는 것이 바로 concurrency( 동시적 프로그래밍이다) 차후에 설명.

간단한 방법으로는 한개의 interrupt를 처리하고 있을 때는 다른 interrupt를 disable 시키는 것이 있을 수 있다.

또한 OS는 다양한 lock 기술을 활용해 커널 안에서 다수의 활동이 진행될 수 있도록 해준다.

 

 

#5. 요약

 => CPU virtualization을 구현하기 위한 low-level mechanism이 여러개가 있지만 그 중에서도 이 단원에서는 Limted

Direct Execution에 대해 다뤄보았다.

 

: Basic idea는 심플하다. 먼저 프로그램을 CPU에서 실행시키고 싶다면, 프로세스가 OS의 도움없이 할수 없는 행동들에 제한을 두어 하드웨어를 세팅해야 한다는 것이다. 비유적으로, OS가 CPU를 baby proofing한다고 표현할 수도 있겠다. Trap handler를 세팅하고, interrupt timer를 설정하여 시작하고, 프로세스를 restricted mode에서만 실행하면서 엄격하게 관리를 한다고 볼 수 있겠다.

 

-> 이를 통해 프로세스를 효율적으로 관리하고, OS intervention(간섭)이 들어가는 것은 privileged operation을 실행하거나, 한 프로세스가 CPU를 너무 오래 차지하고 있어서 문맥 전환이 필요한 경우 두가지 에만 해당하게 만들 수 있다는 것이다.

 

간단한 용어 정리 부분. 참고하자

 

=> 번역..너무 힘들었다.. 다시 하기 싫ㅎ다...

 

'Computer Science > Operating system' 카테고리의 다른 글

Ch 5-3) Process scheduling  (0) 2020.05.31
Ch 5-(1),(2) Process Scheduling  (0) 2020.05.16
ch4 - Threads& Concurrency  (0) 2020.05.04
ch.3-2,3 프로세스 생성, 종료 & IPC  (0) 2020.05.04
Operating system- chapter 1  (0) 2020.04.10