수정입니다

6. Mechanism: Limited Direct Execution 본문

전공/운영체제

6. Mechanism: Limited Direct Execution

nongdamgom 2023. 12. 29. 14:44

 

운영체제는 time sharing을 통해서 CPU 를 process에 공유한다고 했다.

 

여기서 두가지 issue 존재

  1. Performance - context switching overhead
  2. Control - process에 넘긴 CPU 주도권을 어떻게 다시 가져오고 유지할 지

 

 

Direct Execution

  •  그냥 프로그램 실행 후 끝날 때까지 기다렸다가 다시 control을 가져오는 방식
  • 하지만 프로그램에 어떤 limit도 가하지 않는다면, 운영체제로서의 역할을 한다고 말하기 어렵다
  • +) 여러가지 문제 존재

 

Problem 1 : Restricted Operation

  • process가 CPU처리 이외에 disk의 I/O처리나 다른 system resouces를 필요로 할 때 어떻게 할 거냐?
  • process가 하드웨어의 이리저리 전부 접근하고 제어권을 뺏기는 경우가 생길 수 있음

 

Solution : Using protected control transfer

  • User mode : application이 돌아가면서 hardware resources에 완전하게 접근하지 못함 (low privilege level)
  • Kernel mode :  OS가 돌아가면서 hardware에 완전히 접근할 수 있게 함 (high privilege level)

=> user mode에 있는 process들이 system call을 통해 OS에 요청, OS가 kernel mode에서 처리한다

=> 다른 의미가 아니라 prcessor(CPU)에 이런 모드들을 세팅해서 process와 OS를 왔다갔다 하는 거임 

 

 

System call

 

  1. Accessing the file system
  2. Creating and destroying process
  3. Communicating with other processes
  4. Allocating more memory

OS가 이러한 주요한 함수들을 process들에 carefully expose 함

=> OS가 process들이 사용할 수 있도록 핵심적인 기능을 모아놓은 것이 system call

=> sys call이 process의 요청이 정당한지 아닌지 판단 후 실

 

 

그렇다면, User mode에 있는 process들은, 어떻게 system call을 호출 할 수 있을까?

=> Trap instruction

  • Jump into the kernel
  • Raise the privilege level to kernel mode

=> application(user mode)에서 실행하는 명령어

 

=> Return-from-trap instruction

  • Return into the calling user program
  • Reduce the privilege level back to user mode

=> OS가 kernel mode에서 실행하는 명령어 

 

Limited Direction Execution Protocol

  • 제일 처음, OS가 trap table을 초기화(각 handler의 주소로, trap table의 jump 명령을 채움)
  • fork()를 통해 process 생성(fork도 syscall이므로 return-from-trap 존재)

 

** kernel stack의 두가지 기능 => kernel stack은 각 process마다 가지고 있다.

1. OS 함수를 실행할 때 필요한 local var, input para, return addr를 저장하는 역할

2. user mode에서 kernel mode로 들어갈 때 user mode의 register를 저장, 다시 돌아갈 때 복원하는 역할

 

이후 실행하며 sys call 호출 flow

OS(kernel mode) Hardware Program(user mode)
    system call 호출, trap into OS
  1. save regs to kernel stack
2. move to kernel mode
3. jump to trap handler
 
Handle trap
Do work of system call
return-from-trap
   
  1. restore regs from kernel stack
2. move to user mode
3. jump to pc afer trap
 
    retrun from main

 

  • user process는 system call handler의 주소를 모른다.
  • 따라서 exception(system call, interrupt)가 발생하면 다 멈추고 trap table로 가게 pc를 수정
  • hardware에서 3가지 처리 후 handle trap

 

 

process A에서 read() syscall 호출, trap instruction 발생

 

 

trap inst 발생 시, 모든걸 다 멈추고 가야하기 때문에, 그때까지 CPU에서 하던거 저장해야됨

 

 

1. save regs to kernel stack

저장할 register들을 A의 kernel stack에 저장

 

 

2. move to kernel mode

저장 후 proecess A를 kernel mode로 변경 (privilege level 상승)

 

 

3. jump to trap handler

trap table에서 명령어에 맞는 걸 찾아서, 그 syscall handler로 jump 

 

 

syscall_handler에서 뭔가를 또 처리해야하니, register 내용이 변경 되었을 것 (register는 공용이다)

 

 

handler에서 다 처리한 후, return-from-trap을 만나면, 다시 hardware 처리 시작

이건 Limited Direct Execution 예시이므로, 그냥 kernel stack에 저장된 A regi를 바로 복원한다

(A가(A혼자) 하드웨어에 막 접근하지 못하도록 limit을 주는 예시)

 

 

 

 

Problem 2 : Switching Between Processes

  • process들을 서로 바꿔줄 때, OS가 어떻게 다시 control을 가져올까?
  1.  A cooperative Approach : Wait for system calls - process가 양보 
  2.  A Non-Cooperative Approach :  The OS takes control - 제 3의 handler를 이용해서 OS가 제어권을 얻어냄

 

 

A cooperative Approach : Wait for system calls (별로 안좋다고 한다)

  • process가 주기적으로  yield()  같은 system call을 만들면서 CPU 제어권을 포기함
  • +) 뭔가 잘못된 걸 했을 때 OS에게 제어권 넘김 ( 0으로 나눈다거나, 접근불가 메모리에 접근한다거나 )

** 만약 process가 infinite loop에 들어가면 machine을 reboot 하는 것 이외에 OS가 regain을 할 기회 자체가 없어짐

 

 

A Non-Cooperative Approach :  The OS takes control

  • A timer interrupt  - OS가 주기적으로 이걸 발생시킴
  • interrupt가 발생되면 
  • 1. 현재 실행 중인 process가 halt 되고
  • 2. 그 program의 현재 상태를 저장하고
  • 3. OS에서 미리 구성된 interrupt hanlder를 실행함

 

Saving and Restoring Context 

  • 운영체제가 제어권을 잡으면, Scheduler 가 결정을 내림
  • 현재 process를 계속 실행 vs 다른 process로 바꾸기
  • 다른 process로 바꾸는 결정을 하면, OS가 context switch를 실행한다. 

** context == 문맥 == 그니까 register를 바꿔준다고 생각하면 된다

 

 

Context Switching (assembly code로 짜야한다)

 

1. 현재 process의 PCB에 register 저장(r0~r12 : general, r15 : pc, r13 : sp)

2. 바꿔줄 process의 PCB에 저장된 register를 CPU로 복원

3. 바꿔줄 process의 kernel stack으로 switch

 

 

Limited Direction Execution Protocol(Timer interrupt)

 

 

process A가 실행 중일 때 Timer interrupt가 들어옴 

 

 

실행 중이던 process A의 현재 실행 상태를 A의 kernel stack에 저장 

 

 

process A의 mode를 kernel mode로 변경

 

 

timer interrupt에 맞는 handler를 찾아서 jump, switch()를 실행

 

 

1. Save a few register value for the current process onto its PCB (r0~r12 : general, r15 : pc, r13 : sp)

switch()를 실행하면서 이 kernel내에서 현재까지의 진행상황을 A의 PCB에 저장함

그래야 A가 다시 돌아왔을 때 kernel내에서 어디까지 진행했는지를 보고 복원을 하든 뭘 하든 할거 아님

(위에서 kernel stack에 저장한건, 실제 CPU 위에서 user mode에서 진행중인 A의 진행 상황)

 

 

저장했으면 switch를 하고 B를 실행 (restored은 아래에서)

 

 

아까 바꾼 A를 다시 바꿀거임.

 

 

2. Restore a few for the soon-to-be-executing porcess from its PCB

3. Switch to the kernel stack for the soon-to-be-executing process

A PCB에 저장 해 놓은 reg를 복원하고, A의 kernel stack으로 바꿔줌

 

 

return-from-trap을 만나면 A의 kernel stack에 저장되어 있던 reg를 다시 복원

 

 

다시 A를 실행 

 

 

'전공 > 운영체제' 카테고리의 다른 글

9. Scheduling: Proportional Share  (0) 2024.01.01
8. Scheduling: The Multi-Level Feedback Queue  (1) 2023.12.30
7. Scheduling: Introduction  (0) 2023.12.30
5. Interlude : Process API  (0) 2023.12.29
4. The Abstraction: The Process  (0) 2023.12.28