운영체제(OS)

[OS] Limited Direct Execution

서노리 2022. 10. 17. 23:43
반응형

Direct Execution

direct execution이란 프로그램에서 어떤 코드를 돌리던지 os가 간섭하지 않는 것을 뜻한다.

즉, os가 pcb를 생성하고 인자를 stack에 할당해주는 초기 작업을 다 마친 후에 프로그램의 main()을 호출해서 실행함으로써 os에서 프로그램으로 영역이 넘어간 다음에는 어떠한 연산을 하더라도 간섭하지 않는 것이다.

문제점

  • 프로세스가 원치 않는 일을 하지 않는다고 보장할 수 없음
  • os가 이를 중단시키고 다른 프로세스를 실행시킬 수 없음(time sharing 불가)

os가 실행 중인 프로그램을 제어하지 못하면 os가 아니라 라이브러리에 불과하다.
이러한 문제점들 때문에 os는 제한적 직접 실행(Limited Drect Execution) 방식을 따른다.

UserMode와 Kernel Mode

위 direct execution의 문제점을 해결하기 위한 방법으로 특수 권한이 필요한 명령들은 kernel 모드에서 실행하고 그외 일상적인 연산들에 대해서는 user 모드에서 실행하도록 하는 것이다.

프로그램 상태 워드(psw)의 한 비트를 사용하여 수행 모드를 나타낸다(0은 커널모드, 1은 유저모드)

Interrupt

인터럽트란 HW에서 비동기적으로 발생하는 전기적 신호로 프로세스가 유저모드에서 커널모드로 변경되도록 한다.

인터럽트는 HW 인터럽트와 SW 인터럽트로 구분할 수 있다.

  • HW 인터럽트
    현재 수행중인 프로세스와는 독립적으로 외부에서 유발되는 인터럽트로 I/O의 종료 및 Time quantum이 다되어 수행중인 프로세스를 전환해야하는 경우(clock interrupt)가 있다.

 

  • SW 인터럽트
    시스템콜과 예외처리로 구분되며 사용자가 명시적으로 시스템콜을 호출하거나 프로그램 수행 중 예외가 발생하면 Trap 특수 명령어가 실행된 후 커널모드로 전환된다. 특수 명령어의 수행이 종료되면 return-from-trap을 발생시켜 다시 유저모드로 돌아간다.

HW 인터럽트 처리 과정

PIC(Programmable Interrupt Controller)가 여러 HW로부터 interrupt 정보를 수집하고 이를 cpu에 전달한다. cpu는 커널의 IDT(Interrupt Descriptor Table)에서 해당 인터럽트의 entry 포인터 값을 찾는다. 이때 유저모드에서 커널모드로 전환되게 되며 찾은 포인터 값은 interrupt handler 내부의 특정 함수를 가리키게 되는데 이를 이용해 인터럽트 처리가 수행된다.

 

시스템 콜 처리 과정

fork()를 호출하는 예시를 통해 시스템 콜 처리 과정을 알아보자. 시스템 콜도 결국 인터럽트이기 때문에 위의 인터럽트 처리과정과 유사하다. fork() 함수는 assembly 코드에서 movl과 int 명령어로 변환된다. movl 2, %eax는 eax 레지스터에 2를 저장하라는 뜻이고 int $0x80은 커널의 IDT에서 0x80 번지로 찾아가라는 뜻이다. IDT의 0x80 번지에 있는 시스템 콜의 entry 포인터 값을 따라간 interrupt handler는 시스템 콜들에 대한 주소를 저장하는 sys_call_table을 갖고 있는데, 해당 table에서 sys_fork()에 대한 주소를 찾은 뒤 system call handler에 의해 sys_fork() 명령어가 실행된다.

Process 전환

schedule() 함수는 다음 실행할 process의 PCB를 return하는 함수이다. PCB란 Process Control Block으로 os가 process를 추상화한 것이다. linux에서는 PCB가 task_struct type이다. 이렇게 얻어낸 다음 process의 PCB와 현재 실행 중이던 process의 PCB를 switch() 함수에 인자로 넣으면(switch(prev PCB, next PCB)) 문맥 교환이 수행된다. 자세한 단계는 아래와 같이 진행된다.

  1. 현재 실행 중이던 process의 context를 저장
  2. 현재 실행 중이던 process의 PCB를 갱신 (상태를 Ready, Block, Sleep, Zombie 등으로 변경)
  3. PCB를 os의 schedule 정책에 따른 특정 queue로 이동
  4. os의 schedule 정책에 따라 다음 process를 선택
  5. 선택된 process의 PCB를 갱신 (상태를 Running으로 전환)
  6. 선택된 process가 이전 수행에서 사용했던 context를 복원

위에서 정리한 9단계 State를 참고하면, 아래의 경우에 대해 각각의 process 전환 이후의 상태를 특정할 수 있다.

  1. exit() → schedule() → switch() : zombie 상태
  2. I/O → schedule() → switch() : block 상태
  3. clock interrupt → schedule() → switch() : runnable (또는 memory가 부족할 경우 suspend) 상태

Mode Switch vs Process Switch

mode의 전환은 Kernel mode / User mode 사이의 전환을 말한다. mode 전환은 현재 실행 중인 process의 상태 (running, runnable, zombie …)를 바꾸지 않고 수행 가능하다. context를 따로 저장할 필요도 없기 때문에 많은 연산을 요구하지 않는다. 반면 process 전환은 실제 context를 따로 저장 및 교환해야 하기 때문에 mode 전환에 비해 훨씬 더 많은 연산을 요구하게 된다.

 

Process 전환의 한계

기본적으로 대부분의 os는 중첩 interrupt를 금지한다. 즉, 이미 interrupt가 발생해서 처리 중인 경우에는 그 사이에 발생된 새로운 interrupt에 대해 처리하지 않는다는 것이다. (락 기법 사용)


 

반응형

'운영체제(OS)' 카테고리의 다른 글

[OS] 가상 메모리(Virtual Memory)  (0) 2022.10.18
[OS] 물리 메모리 관리 기법  (0) 2022.10.18
[OS] Scheduling  (0) 2022.10.17
[OS] Process Abstraction  (0) 2022.10.14
[OS] Introduction to Operating Systems  (0) 2022.10.14