시스템 프로그래밍/Operating Systems: Three Easy Pieces

6. Mechanism: Limited Direct Execution

맛있는김치찜 2020. 10. 16. 00:02

서론

프로세스는 CPU위에서 돌아간다. 

프로세스의 수 만큼의 CPU가 없기 때문에 time sharing을 통해서 CPU가상화(virtualization)를 구현한다.

이 가상화를 구현할 때 성능(performance)은 최대한 유지하면서 프로세스를 제대로 제어(control)할 수 있어야 한다. 

 

Basic Technique: Limited Direct Execution

Problem #1: Restricted Operations

우선 limited direct execution과 반대의 개념인 directed execution을 알아보자.

directed execution는 프로세스를 CPU위에서 바로 돌리는 것이다. 

프로세스가 CPU를 직접 사용하니 이 방법을 사용하면 프로그램의 성능이 높아진다는 장점이 있다.

하지만 만약 사용자가 만든 프로세스가 CPU나 중요한 메모리의 내용을 함부로 사용한다면? 

바람직하지 않은 결과가 나올 것이다. 

그래서 나온 방법이 'limited(제한적인)' direct execution이다.

 

limited direct execution에서는 프로세서(CPU)의 동작 모드가 2가지로 나뉜다.

user mode: 프로세스가 I/O 같은 위험한 동작을 수행할 수 없다.

kernel mode: 프로세서의 제어권을 os가 가져간다. I/O 같은 중요한 동작을 수행할 수 있다.

 

system call같은 동작을 수행할 때에도 kernel mode에서만 수행할 수 있다.

이때 user mode에서 kernel mode로 들어가는 연산을 trap instruction이라고 부르고

kernel mode에서 user mode로 나오는 연산을 return-from-trap instruction이라고 부른다. 

 

trap 연산을 수행하면 user mode에서 수행하던 프로세스는 동작을 멈추고 kernel mode로 들어간다.

이때 user mode에서 수행하던 프로세스의 상태를 백업할 필요가 있다.

그래야지 kernel mode에서 중요한 연산을 수행하고 다시 돌아왔을때 이어서 동작할 수 있기 때문이다.

예를 들어 x86에서는 kernel mode로 들어갈 때 user mode의 pc와 stack pointer, 범용 레지스터들은 kernel stack에 백업된다.

 

os는 부팅할때 시스템콜이 호출되었을 때 그 함수가 저장되어 있는 표(trap table)를 초기화한다.

다음은 limited direct execution이 부팅부터 작동하는 순서도이다.

프로세스는 시스템콜을 호출할때 시스템콜의 주소가 아닌 그 번호를 이용해 호출한다.

이는 프로세스가 그 주소로 직접 접근하여 시스템의 중요한 부분을 건드리는 것을 미연에 방지하는 장치이다.

 

Problem #2: Switching Between Processes

time sharing을 이용해 프로세스들이 cpu를 번갈아 사용하면 실행 도중에 다른 프로세스에게 cpu를 넘겨줘야 하는 일이 반드시 생긴다.

이때 실행하던 프로세스는 다시 자연스럽게 이어갈 수 있게 현재 자신의 상태(pc, stack pointer, 범용 레지스터)를 백업한다.

A Coorperative Approach: Wait For System Calls

coorerative approach프로세스가 특정한 시스템 콜을 발생시키면 os가 다른 프로세스에게 cpu 제어권을 넘겨주는 방식이다(협력적인 프로세스).

또한 0으로 나누는 연산이나 프로세스가 접근해서는 안되는 메모리 구역에 접근해도 cpu제어권을 다른 프로세스에게 넘긴다.

많은 운영체제들이 선택했던 방법인데 매우 큰 문제점이 있다.

: 만약 프로세스가 무한루프에 걸려 제어권을 넘겨주지 못한다면?

이런 상황이 발생하면 컴퓨터를 재부팅 하는 방법밖에는 남아있지가 않다.

 

 

A Non-Cooperative Approach: The OS Takes Control

non-cooperative approach타이머 인터럽트가 주기적으로 발생하면 os가 강제적으로 다음 프로세스로 바꾸는 방식이다.

타이머 인터럽트가 발행하면 실행하는 프로세스가 바뀐다는 뜻인데, 이를 위해 os는 타이머 인터럽트가 발생하면 어떤 코드를 실행시킬지 하드웨어에게 미리 알려줘야한다.

 

Saving and Restoring Context

프로세스 실행 도중에 타이머 인터럽트가 발생하면

1. 현재 실행중인 프로세스는 user mode의 상태(pc, stack pointer, 범용 레지스터)를 커널스택에 저장하고 kernel mode로 진입한다.

2. 인터럽트 핸들러를 수행하다가 다른 프로세스로 변경하라는 switch()같은 함수를 만나면

3. kernel mode의 상태를 pcb(process control block)이라는 특별한 구조체에 저장한다.

4. 다음 프로세스가 이전에 저장했던 상태로 복구한다.

5. 다음 프로세스가 이전에 실행하다가 끊겼던 부분부터 이어서 실행한다.

이러한 과정을 context swtiching이라고 부른다.