Limited Direct Execution
운영체제는 여러 작업들이 동시에 실행되는 것처럼 보이도록 물리적인 CPU를 공유한다.
- 한 프로세스를 잠깐 실행하고 다른 프로세스를 잠깐 실행하고 이런식으로 계속해서 잠깐식 실행시키는 방법으로 CPU를 가상화한다. ( CPU 시간을 나누어 쓰는 방법 )
위와 같은 방법을 사용시 해결해야 할 점
- 성능 저하
- 시스템에 과한 오버헤드를 주지않고 가상화를 구현할 수 있을까?
- 제어 문제
- CPU에 대한 통제를 유지하면서 프로세스를 효율적으로 실행시킬 수 있는 방법은 무엇일까?
기본원리 : 제한적 직접 실행 ( Limited Direct Execution )
- 직접 실행은 "프로그램을 CPU 상에서 직접 실행시키는 것"
- 프로그램 시작시 프로세스 목록에 해당 프로세스 항목을 만들고, 메모리를 할당하며 프로그램 코드를 디스크에 탑재하고 진입적을 찾아 그 지점으로 분기하여 사용자 코드를 실행.
- 한 번 실행한 프로세스는 멈추지 않기에, 제어할 수 없음
- 이 제한없는 직접 실행은 아래와 같은 문제점이 존재
- 프로그램을 직접 실행시킨다면 프로그램이 운영체제가 원하지 않는일을 한다는 것을 어떻게 알 수 있는가?
- 프로세스 실행 시, 운영체제는 어떻게 프로그램의 실행을 중단하고 다른 프로세스로 전환을 할 수 있는가? → 즉, 시분할 기법을 어떻게 구현하는가?
문제점1 : 제한된 연산
직접 실행의 장점은 빠르게 실행되는 것.
하지만 실행중 특수한 종류의 연산( 디스크에 대한 I/O, CPU 메모리에서 더 많은 리소스를 요청하는 것 .. )을 하려고 할 시 문제가 됨.
프로세스가 I/O 및 기타 작업들을 모두 수행하도록 하는 방법
- 예를 들어, 파일에 대한 접근을하기 전 권한을 확인하는 파일 시스템을 만든다고 하자.
- 그런데, 프로세스가 기타 작업들을 모두 수행 할 수 있도록 하면 권한을 부여할 수 없기 때문에 보호 기능을 수행할 수 없게 됨.
이를 해결하기 위해, User mode와 Kernal mode로 상태를 구분
- User mode는 수행할 수 있는 작업에 제한을 둠으로써, 기타 작업을 실행하려하면 오류를 발생시킴.
- Kernel mode는 I/O 같이 권한이 필요한 작업을 할 때 쓰는 상태로, 이 Kernel mode로 실행해야 오류가 발생하지 않음.
그런데, 만약 User mode의 프로세스가 Kernel mode에서 수행이 가능한 작업을 하고 싶을 때 어떻게 해야할까?
- OS에서 시스템 콜을 제공한다.
- 시스템 콜은 User mode의 프로세스가 Kernel mode에서 수행가능한 작업을 실행할 수 있게한다.
- 시스템콜이 실행되면, trap 명령으로 권한을 바꾸고 수행이 끝나면 OS가 return-from-trap 명령을 통해 원래의 권한으로 돌아옴.
- trap 명령이 실행되면 프로세스는 pc, flag, register 정보를 kernel stack에 넣습니다. 그 후 return-from-trap 명령이 수행되면 이 데이터를 모두 pop하여 다시 User mode에서 사용할 수 있게 합니다.
OS는 trap을 어떻게 사용할까?
- trap table이라는 것을 사용. 이는 컴퓨터가 부트될 시 초기화됨.
- 이 trap table에는 각 명령어를 실행하기 위한 trap handler들이 들어있다.
- 이를 통해 trap을 사용함.
실제로 trap을 사용하는 과정
- 부팅시 trap table 초기화
- 프로세스가 생성되면 user mode에서 실행
- kernel mode에서 실행이 필요하면 ( system call 이 발생하면), trap 되고 그 후 시스템 콜이 종료되면 return-from-trap을 통해 다시 user mode로 복귀.
- 프로세스 작업이 끝나면, 프로세스를 제거
문제점2: 프로세스 간 전환
직접 실행의 문제점은 프로세스간 전환이 불가능하다.
이러한 프로세스를 바꾸려면 OS가 제어권을 가지고 와서 프로세스 전환을 제어해주어야함.
이것을 해결하기 위한 방식은 두가지가 있음.
협조 방식 : System Call 호출시 까지 대기
- System call이 발생하거나 비정상적인 행위를 하게되면, 제어권이 OS에게로 넘어옴. 이 때 OS가 프로세스를 전환.
- 문제점
- System call이 발생하지 않아 제어권이 넘어오지 않는 경우
- 프로그램이 무한 루프에 빠져 System call을 호출 할 수 없는 경우
이를 해결하기 위해 time interrupt를 통한 프로세스 전환을 사용.
비협조 방식 : 운영체제가 제어권을 확보
timer interrupt를 사용하는 방법.
- 타이머는 수 밀리 초마다 인터럽트라고 불리는 하드웨어 신호를 발생시키도록 프로그램 할 수 있음.
- 인터럽트가 발생 했을 때, OS는 현재 수행 중인 프로세스를 중단하고 해당 인터럽트에 대한 interrupt handler를 작동시킨다.
- 위 과정에서 자연스럽게 OS에게 제어권이 넘어가고, 운영체제는 필요한 작업을 수행할 수 있다.
- trap table과 유사하게 interrupt table에 interrupt handler를 정의하고 이를 사용해서 처리하는 방식을 사용.
Context save and restore
- 프로세스를 전환할 때 OS는 Context switch라는 코드를 실행
- Context switch는 현재 실행 중인 프로세스의 레지스터 값들을 커널 스택 같은 곳에 저장(Context save)하고 새롭게 다시 실행 될 프로세스의 커널 스택으로부터 레지스터 값을 복원(Context restore)하는 것.
병행실행 문제
- 시스템 콜을 처리하는 도중에 타이머 인터럽트를 발생시키면 어떻게 될까?
- 인터럽트를 처리하는 동안 다른 인터럽트가 발생되면 어떻게 될까?
실제로 많이 일어나는 일.
여러가지 해법
- Disable interrupt
- 다른 인터럽트 처리 중일 때 발생하는 인터럽트는 무시.
- Priority
- interrupt에 우선순위를 줘서 순차적으로 처리.
- Locking mechanism
이것은 병행성에 관한 문제. 병행성 단원에서 자세히 배워보자.
요약
Direct Execution은 여러가지 문제가 있기에, Limited Direct Execution을 사용. Limited Direct Execution은 아래와 같은 작업을 함.
- 프로세스 권한 작업을 위해서 Mode switching을 사용
- 프로세스 전환(time sharing)을 위해 Context switching을 사용.