[04] 인터럽트와 예외

 01. 시작


부트스트랩의 이해, 커널의 로드, Real Mode에서 Protected Mode의 전환까지를 알아 보았다.


이번에는 Protected Mode 진입을 위해서 준비해야될 다른요소인 IDT에 대해서 알아보도록 하자.


IDT구성 및 인터럽트를 처리 할수 있도록 여러가지를 구성 해보며, 대표적인 타이머, 키보드 인터럽트와


예외처리를 알아보도록 하겠다.


 


 02. 인터럽트와 예외


 2.1 Interrupt and Exception Overview


하드웨어 혹은 소프트웨어 분야에 있는 사람들에게는 위의 두 단어는 익숙한 단어라고 생각이 든다. 그럼 인터럽트와 예외에 대해서 잠시 언급을 한뒤


실제적으로 인터럽트와 예외를 설정하고 처리하는 과정에 대해서 알아보도록 하자.



Intel Architecture Software Developer's Manual을 참고하면 인터럽트는 I/O장치에 의해서 발생되는 비동기적인 이벤트 이며, 예외는


동기적인이벤트(즉 명령어가 실행 도중 프로세서가 미리 정해둔 하나이상의 상태가 검출이 될 경우)를 말하고 있다.


여기서 동기적/비동기적 이라는 용어를 사용한 이유는, 인터럽트의 경우 프로그램 실행 도중 랜덤하게 발생되기때문에 비동기라는 용어를


예외의 경우에는 명령어 실행 도중 프로세서가 에러 상태는 검출 했을 경우에만 발생 하기 때문에 동기적이라는 용어를 사용했다.



쉽게 정리하자면, 프로그램이 실행 도중 내부적(프로그램 명령어 실행) 또는 외부적(I/O 장치)에서 어떠한 이벤트가 발생이 되고 이 상태를


프로세서에게 처리를 요청하게 되는데 이 요청이 바로 인터럽트와 예외라고 하는 것이다.



일반적으로는 인터럽트를 하드웨어적으로 관련된 이벤트를 말할때 쓰이고, 예외는 소프트웨어적으로 관련된 이벤트를 말할때 쓰이는데 보통은


인터럽트라는 말로 통합해서 많이 쓰인다.


 


 2.2 IDT (Interrupt Descriptor Table)


인터럽트를 구현하기 위해서는 인터럽트에 대한 처리 방법을 정리를 해야되는데 이것을 정리해서 모아둔 곳이 IDT라고 보면 되겠다.


Protected Mode 진입을 위해서 각각의 메모리 영역을 설명하기 위해서 GDT를 만든것과 마찬가지로 보호모드에서 인터럽트를 처리 역시 IDT라는


것을 만들어 주어야 한다. GDT와는 달리 IDT는 첫 번째 디스크립터도 사용이 된다.


 


IDT 역시 GDT와 모양을 비슷하며 요소에는 해당 인터럽트가 어디서 실행되어야 하는지에 대한 설명이 되어있다고 보면 되겠다. 이 테이블은


보통은 256개로 구성이 된다. 아래그림을 참고 하자.


IDT.JPG


 < Interrupt Descriptor Table >




  • Offset: 인터럽트 핸들러가 위치하고 있는 오프셋의 물리주소이다. 상/하위 주소를 입력한다.



  • Segment Selector: 인터럽트 핸들러가 위치하고 있는 코드 세그먼트의 셀렉터 값을 입력한다. 하지만 인터럽트 핸들러의

                               경우 보호모드에서 동작하기때문에 커널 코드 세그먼트 셀렉터 값을 입력하면 된다.



  • P: 현재의 커널 코드 세그먼트가 RAM 상에 존재 여부를 나타낸다. 항상 '1'로 설정



  • DPL: 실행될 특권레벨을 지정하는 것이다. 커널 모드에서 동작하기 때문에 '00'



  • D: 지정한 코드 세그먼트가 16비트인지 32비트인지를 알려주는 것이다. 16비트: '0', 32비트: '1'



 


 2.3 IDT 등록


GDT와 마찬가지로 IDT역시 레지스터에 등록을 해주어야되며, 명령어중 lidt 명령을 통해서 IDTR 레지스터에 IDT에 대한


크기 및 시작점 주소가 저장이 되게 된다. 등록 과정에 대한 것은 GDT와 같으므로 03 Protected mode로의 전환 에서의 GDT


등록 과정 그림을 참고하기 바란다.




  1. lidt[idtr]



위의 코드로 IDTR에 IDT가 등록이 되며 idtr은 IDT의 크기와 시작점 주소가 저장되어있는 곳의 포인터이다.



 IDTR.JPG


< IDTR 레지스터를 통한 IDT 참조과정 >



 2.4 인터럽트 처리 과정


< 인터럽트 처리 순서 >




  1. IDT에서 해당 인터럽트 번호에 대한 핸들러가 위치한 코드 세그먼트와 오프셋을 찾는다.



  2. GDT에서 해당 핸들러가 위치한 세그먼트로의 접근이 가능한지 판단한다.



  3. 접근이 가능하다면 해당 세그먼트에 위치한 핸들러를 실행한다.



 위의 순서로 인터럽트가 발생하게 되면, 인터럽트가 실행이 되게 된다.


 IDT_처리과정.JPG


< 인터럽트 처리 과정 >


 2.5 PIC 설정


외부 I/O장치에 대한 인터럽트 처리를 위해서는 8259A 칩을 통해서 설정을 해야된다.


PIC에 대한 설명은 참고. Programmable Interrupt Controller (PIC)에서 설명을 하고 있으니, 이곳을 참고하기 바란다.


 


 2.6 Timer Interrupt 구현


IDT 테이블에 대한 구성 및 등록에 대해서는 GDT 등록 및 구성과 과정이 거의 동일 하므로 GDT 등록 부분을 참고 하면 되겠고,


여기서는 인터럽트 중 타이머 인터럽트를 구현 해보자.


타이머 인터럽트 구현을 위해서는



  1. 타이머 인터럽트 디스크립터 구성

  2. 타이머 인터럽트 핸들러 구현

  3. IDT 테이블에 타이머 인터럽트를 등록 (번호 == IDT 인덱스)


 


위의 내용을 참고하여 구성을 하면 되겠다.




  1. idt_timer: 

     dw isr_32_timer

     dw 0x08

     db 0

     db 0x8E

     dw 0x0001



타이머 인터럽트에 대한 디스크립터 내용이다. 핸들러 및 세그먼트, 오프셋, 특권레벨 등으로 구성이 되어있다.


 




  1. isr_32_timer:

     push gs

     push fs

     push es

     push ds

     pushad

     pushfd



  2.  mov al,0x20               ; PIC를 리셋하는 코드이다.

     out 0x20,al               ; 리셋을 하지 않을 경우 인터럽트가 무시된다.



  3.  mov ax, VideoSelector

     mov es, ax

     mov edi, (80*2*2)

     lea esi, [msg_isr_32_timer]

     call printf

     inc byte [msg_isr_32_timer]

     

     popfd

     popad

     pop ds

     pop es

     pop fs

     pop gs

     

     iret



타이머 인터럽트 핸들러에 대한 코드이다. 코드의 내용은 문자열을 출력하는 것 뿐이다.


핸들러에 진입할때와 리턴할때 레지스터 및 현재 상태를 스택에 저장하고 복원하는 과정은 중요하니 잘 보도록 하자.


핸들러루틴중 PIC를 리셋을 해주어야 되는 부분이 있는데 이것은 PIC 설정을 할때 ICW4 단계에서의 PIC 리셋의 자동/수동 설정


부분과 연관이 있으므로 유의해서 설정하기 바란다.


 


 2.7 Exception


 이번에는 예외에 대한 처리 방법에 대해서 알아보자. 인터럽트와 마찬가지로 예외에 대한 처리도 역시 IDT에 등록을 해서 처리를


 하도록 해주면 된다. 하지만 예외처리에 대한 번호는 IRQ번호와 같기 때문에 번호 충돌에 대한 처리를 해주어야 된다.


 이에 대한 처리방법은 PIC 에 대한 설정을 할때, 인터럽트 번호를 CPU에 알려줄때 해당 번호를 매핑해서 알려주도록 하면 인터럽


 트와 예외 번호에 대한 충돌 처리를 할 수 있다. PIC 번호에 대한  설정은 참고. Programmable Interrupt Controller (PIC)


 참고하면 ICW2 단계에서의 설정을 참고 할 수 있다.


 


< Exception 종류 > 


 -------------------------------------------------------

    Vector number   Description

 -------------------------------------------------------

           0        Divide Error (Division by zero)

           1        Debug Interrupt (Single step)

           2        NMI Interrupt

           3        Breakpoint

           4        Interrupt on overflow

           5        BOUND range exceeded

           6        Invalid Opcode

           7        Device not available (1)

           8        Double fault

           9        Not used in DX models and Pentium (2)

          10        Invalid TSS

          11        Segment not present

          12        Stack exception

          13        General protection fault

          14        Page fault

          15        Reserved

          16        Floating point exception (3)

          17        Alignment check (4)

     18 ~ 31      Reserved on 3/486


    32 ~ 255      Maskable, user defined interrupts

   -------------------------------------------------------


 


 3. 출력화면



 


 4. 참고 자료 



  • Intel Architecture Manual

  • 만들면서 배우는 OS 커널의 구조와 원리


이 글은 스프링노트에서 작성되었습니다.

by 블랙호크 | 2007/08/31 23:39 | ┣ OS | 트랙백 | 덧글(0)

트랙백 주소 : http://raptors.egloos.com/tb/614908
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]

:         :

:

비공개 덧글

◀ 이전 페이지다음 페이지 ▶