본문 바로가기

Computer Science/OS

2-3. Virtualization: Limited Direct Execution

Limited Direct Execution

  1. OS는 프로그램 코드를 메모리에 Load한다. (process의 address space에)
  2. 프로그램의 run-time Stack이 할당된다. (지역 변수, 함수 인자, return 주소)
  3. main(argc, argv)로 stack init
  4. Heap 설정 (Dynamically allocated area; malloc())
  5. I/O 설정 (STDIN, STDOUT, STDERR 등)
  6. main(): 프로그램 시작

실행 중인 프로그램에 limit가 없다면, OS는 그 어떤 것에도 제어권을 갖지 않고, 그저 library가 될 것이다.

Direct Execution의 문제

  1. 프로세스가 해서는 안될 instruction (I/O to disk, CPU/Memory 접근)
  2. CPU로 제어권을 다시 가져오기 힘듦. (ex. 무한루프)
  • #1번 문제의 해결방안: Interrupt Handling
    Interrupt는 interrupt handler로 interrupt vector를 통해 제어권을 넘기는데, 해당 interrupt 수행할 함수 주소 (irq 번호)가 들어 있다. Interrupt된 instruction의 주소를 지정해놓아야 한다.
  • Trap (Exception)은 software-generated interrupt로, error나 user request에 의해 발생된다.
    image-20241103234132686
    image-20241103234147229

Dual mode (User mode & Kernel mode)는 OS가 자기자신을 비롯한 다른 system component들을 보호할 수 있게 해 준다.

특권을 가진 몇몇 instruciton들은, Kernel 모드에서만 실행 가능하다.

(ex. I/O request; user mode에서 실행하려 하면 exception → kill)

User는 system call을 사용해 이런 특권 명령을 수행시킨다.

invoke trap(interrupt) → return from trap. mode는 mode bit으로 관리된다.

image-20241103234541086

User는 library function을 이용해 Kernel의 핵심 기능을 이용할 수 있다. (추상화)

image-20241103234621108

System Call Parameter Passing

OS에 인자를 넘기는 방법은 크게 세 가지가 있다.

  1. Register로 넘기기: register 수보다 인자 수가 더 많을 수 있다.
  2. Block이나 Table에 넣고 시작 주소를 넘기기
  3. Stackpush하고 OS가 pop하는 구조
    → 각 OS마다 다르게 정의되어 있다. (Application Binary Interface; ABI)

image-20241103234822355

Interrupt Descriptor Table(IDT, or Interrupt Vector)는 각 interrupt 번호별로 주소가 저장되어 있는 table이다. (booting 때 init)

Trap은 Disk I/O의 완료, keyboard interrupt, system call에 의해 발생되는데, Trap handler는 각 interrupt number에 대응되는 코드이다.

Trap table의 위치를 알려주는 instruction 역시 previleged이다. (user mode에서 실행불가)

  • #2번 문제의 해결방안
    • Cooperative(non-preemtive) Approach
      Process간 전환을 위해 OS가 다시 권한을 되찾는 방법.
      System call 기다리기. Process들은 주기적으로 yield 등을 통해 CPU를 놓아준다. (믿기)
      나누기 0, 접근 불가 접근 → OS로 통솔권 넘기기.
      → 초창기 방식으로, process가 infinite loop에 갇혀 stuck: 재시동만이 답.
    • Non-cooperative Approach
      Timer interrupt를 이용한다. 부팅 때 OS가 timer를 시작하고, 매 수 msec마다 interrupt를 발생시킨다.
      → running process suspend, register save, restore. (Context Switching)

Context Switch

  • Program counter, CPU register, process state, memory-management info와 같은 정보를 process의 context라 부른다.
  • CPU가 다른 process로 switch되면, system은 예전 process의 state를 kernel stack(또는 PCB)에 저장하고 새로운 process의 저장된 state를 불러와서 실행시켜야 한다.
    (이런 OS의 context switching(overhead 발생) code는 빠른 수행을 위해 주로 assembly로 짜인다. )
    시스템마다 처리 방법을 다르게 고안했는데, register들의 묶음이나 special instruction으로 모든 register들을 load/store 할 수 있게 구성한 경우도 있다.

image-20241104000555275

만약, interrupt handlilng 중 다른 interrupt가 발생한다면?

  • Interrupt processing 중인 interrupt를 disable
  • Locking으로 data에 대한 concurrent access를 보호한다.