정보공간_1

[3기 강남 정준호] KeyBoard & Monitor Device Driver 본문

IT 놀이터/Elite Member Tech & Talk

[3기 강남 정준호] KeyBoard & Monitor Device Driver

알 수 없는 사용자 2013. 4. 5. 12:25

 

주제: 키보드와 모니터 디바이스 드라이버

안녕하세요 강남 멤버십 19-2 정 준호 입니다. 밤과 낮의 일교차가 커요.감기 조심하세요!!! 그래도 요센 낮에는 따듯해서 좋네요^^

이전 포스팅에선 Scheduler의 동작 괴정과 Work-Queu에에 대하여 기술하였습니다.

이번 포스팅에서는 사용자와 Communication을 위하여 키보드와 모니터를 추가하는 작업을 기술하도록 하겠습니다.

* SMP 와 MP Boot

* Scheduler

* Work Queue 동작 과정

* 키보드와 모니터 디바이스 드라이버

* Console & Shell

* Testing

 

* 키보드 디바이스 드라이버

키보드 컨트롤러는 PC내부버스와 PortI/O방식으로 연결되어 있으며, Portaddress는 0x60와   0x64를 사용한다.

 

실제 할당된 port는 두 개나 데이터를 읽고 쓸대 접근 레지스터가 다르므로 실   제로는 네 개의 레지스터와 연결된 것과 같다.

 

크기는 모두 1Byte이며 그 중 상태레지스터가 가장 중요 하다. 키보드 컨트롤러의 상태를 표시하기 때문에 킷값을 읽거나 쓰려면 반드시 체크해 야 하는 비트를 포함하기 때문이다.

     

Port Mapping

Port

Read/Write

Register

Description

0x60

Read

Output Buffer

Read Input Buffer

0x60

Write

Input Buffer

Write Output Buffer

0x64

Read

Status Register

Read Status Register

0x64

Write

Control Register

Send Command to Controller

           I/O Port와 Keyboard Controller Register의 관계

     

 Keyboard Register는Control Register, Status Register, Input Buffer, Output Buffer 네 개가   있으며 크기는 모두 1Byte이다.

 

이 중에서 Status Register가 가장 중요한 기능을 담당하는데   Keyboard Controller의 상태를 표시하는 레지스터이기 때문에 키 값을 읽거나 쓰려면 반드시 체크해야 하는 Bit를 포함한다.

     

     

Status Register

Bit

Field

Description

0

OUTB(Output Buffer Status)

- 0: Output buffer empty, don’tread yet / 1: Output buffer full, please read me

1

INPB(Input Buffer Status)

- 0: Input buffer empty, can be written / 1: Input buffer full, don’t write yet

2

SYSF

(System Flag)

- 0: Set after power on reset

- 1: Set after successful completion of the keyboard controllers self-test (Basic Assurance Test, BAT)

3

C/D

(Command Data)

- 0: Last write to input buffer was data (via port 0x60)

- 1: Last write to input buffer was a command (via port 0x64)

4

KEYL(Keyboard Locked)

- 0: Locked / 1: Not locked

5

AUXB

(Auxiliary Output buffer full)

- PS/2 Systems:

0: Determines if read from port 0x60 is valid If valid, 0=Keyboard data

1: Mouse data, only if you can read from port 0x60

- AT Systems:

 0: OK flag

 1: Timeout on transmission from keyboard controller to keyboard. This may indicate no keyboard is present.

6

TIM

(Timeout)

- 0: OK flag / 1: Timeout

- PS/2: General Timeout

- AT: Timeout on transmission from keyboard to keyboard controller. Possibly parity error (In which case both bits 6 and 7 are set)

7

PARE(Parity error)

- 0: OK flag, no error / 1: Parity error with last byte

                                            Status Register의 Bit 구성과 의미

     

 그 외 참고할만한 Keyboard Controller Command는 다음과 같다.   

 

     

Keyboard Controller Commands

Keyboard Controller Command

Description

0x20

Read Keyboard Controller Command Byte

0x60

Write Keyboard Controller Command Byte

0xAA

Self Test

0xAB

Interface Test

0xAD

Disable Keyboard Device

0xAE

Enable Keyboard Device

0xC0

Read Input Port

0xD0

Read Output Port

0xD1

Write Output Port

0xDD

Enable A20 Address Line

0xDF

Disable A20 Address Line

0xE0

Read Test Inputs

0xFE

System Reset

     

 Keyboard와 기타 시스템 제어에 관련된 Keyboard Controller Command

     

 일반적으로Bootloader가 실행되기 전에 Keyboard는 이미 BIOS에 의해 활성화된 상태이다. 라서 Keyboard를 활성화하는 단계를 굳이 수행하지 않아도 Keyboard에서 키 값을 읽는데 아무런 문제가 없지만, 만약을 대비하여 Keyboard를 직접 활성화할 필요성이 있다.

 

Keyboard Controller에서 Keyboard Device를 사용 가능하게 하려면, 커맨드 Port로Keyboard Device 활성화 커맨드인 0xAE를 보내면 된다.

 

하지만 이것은 엄밀히 말하면 Keyboard Controller에서 활성화된 것이지 실제 Keyboard가 활성화된 것은 아니다.

 

Keyboard Controller와 Keyboard는 PS/2 방식의 케이블로 연결되어 있으며 PC의 외부에 존재한다. 그래서 Keyboard에도 활성화 커맨드를 보내줄 필요가 있다. Keyboard에 직접 데이터를 보내는 방법은 커맨드를 전송하지 않고, Input Buffer에 Keyboard로 보낼 커맨드를 직접 쓰면 된다.

 

 Keyboard는 keyboard Controller와 달리 커맨드나 데이터에 대한 응답이 전송되며, 정상적으로 처리한 경우 ACK(0xFA)를 전송한다. 만일 ACK가 수신되지 않으면 수행 도중 에러가 발생한 것이므로, 재시도하거나 작업을 포기해야 한다.

 

     

Keyboard Command

Keyboard Command

Description

0xED

Write LEDs

0xEE

Diagnostic echo

0xF0

Set/Get scancode set

0xF2

Read Keyboard ID

0xF3

Set repeat rate and delay

0xF4

Keyboard enable

0xF5

Set defaults and disable keyboard

0xF6

Set defaults

0xF7

Set all keys to repeat

0xF8

Set all keys to give make/break codes

0xF9

Set all keys to give make codes only

0xFA

Set all keys to give repeat and give make/break codes

0xFB

Set a single key to repeat

0xFC

Set a single key to give make/break codes

0xFD

Set a single key to give make codes only

0xFE

Resend

0xFF

Keyboard reset

     

 LED와 Keyboard 활성화에 관련된 Keyboard Command

     

 앞서 언급했듯이 Keyboard Controller의 Keyboard 활성화는 커맨드 Port에0xAE를 보내는 것으로 가능하다.

Keyboard Controller에 커맨드를 보냈다면 남은 것은 Keyboard에 직접 커맨드 를 보내는 일이다. Keyboard로 커맨드를 보내려면 Input Buffer의 상태 처리와 Keyboard의 응답 처리를 해야 한다.

 

Keyboard와Keyboard Controller는 프로세서와 비교하면 아주 느리게 동작하므로 프로세서가 커맨드를 전송하고 한참을 기다려야 수행이 완료된다.

 

여기서 다루어야 할 문제는 커맨드가 완료될 때까지 얼마나 기다려야 하는 것인가 이다 커맨드를 처리하는 시간은 Keyboard와Keyboard Controller의 상태에 따라 가변적인 부분이기에 Keyboard Controller의 상태를 확인할 수 있는 무언가가 필요하게 된다.

 

이때 사용하는 것이 Keyboard Controller의Status Register(Port 0x64)이다. 위 표에서 알 수 있듯이, Status Register는 Input Buffer 상태 를 표시하는 Bit(Bit 1)와 Output Buffer의 상태를 표시하는 Bit(Bit 0)가 있다.

 

입력 버터 상태 Bit(Bit 1)를 통해 Input Buffer가 비어있는지 확인 후 Keyboard 커맨드를 송신하고, Output  Buffer 상태 Bit(Bit 0)을 통해 Output Buffer에 데이터가 있는지 확인한 후 실행 결과를 읽어 들여 보다 효율적으로 처리할 수 있다.

    

     

(1) 키보드초기화

 일반적인 경우에는 키보드는 이미BIOS에 의해 활성화된 상태이다. 따라서 키보드 활성화를 하는   단계를 굳이 수행하지 않아도 키보드에서 킷값을 읽는데 문제가 없다. 만약을 대비해 키보드를  활성 하다록 했다. 일단 부팅을 하고나면 바로 키보드컨트롤러를 활성화 시켜 준다.

 아래의 블록다이어그램 처럼 처음에 0x64(쓰기모드)를 이용하여 0xAE(키보드디바이스활성화)데   이터를 전송한다. 이렇게 전송을 하면 키보드활성화를 시켜주고 0xFA를 통해 키보드를 동작 시 켜 주므로써 초기화를 할 수 있다.

         

 

 

Keyboard초기화

     

 어셈블리어를 이용하여 포트I/O 레지스터를 읽고 쓰기를 한다.

어셈블리어 함수를 만들어서 In과   Out을 한다. In명령어는 포트I/O어드레스를 지정하는데 DX레지스터를 사용하며 포트에서 값을  읽어 AX레지스터에 저장 한다. 

 

 Out명령어는 반대로 포트I/O어드레스에 데이터를 출력하는 역할을 한다.

기능은 반대지만 포트I/O어드레스에는 DX레지스터를 사용하며 값을 보내는 레지스터로는 AX레지스터를 사용한다.

     

 

 

 

kInPortByte:

 pushrdx ;함수에서임시로사용하는레지스터를스택에저장

    ;함수의마지막부분에서스택에사입된값을꺼내복원

     

 movrdx,rdi ;RDX레지스터에파라메터1를저장

 movrax,0 ;RAX레지스터를초기화

 inal,dx ;DX레지스터에저장된포트어드레스에서한바이트를읽어

    ;AL레지스터에저장

     

 poprdx  ;함수에서사용이끝난레지스터를복원

 ret  ;함수를호출한다음코드의위치로.

     

kOutPortByte:

    pushrdx       ;함수에서임시로사용하는레지스터를스택에저장

    pushrax       ;함수의마지막부분에서스택에삽입된값을꺼내복원

     

    movrdx,rdi   ;RDX레지스터에파라미터1(포트번호)를저장

    movrax,rsi   ;RAX레지스터에파라미터2(데이터)를저장

    outdx,al     ;DX레지스터에저장된포트어드레스에AL레지스터에저장된

                    ;한바이트를씀

     

    poprax        ;함수에서사용이끝난레지스터를복원

    poprdx

    ret            ;함수를호출한다음코드의위치로복귀

 

 

 

(2) 키보드 컨트롤러에서 키 값읽기

     

키보드는 키가 눌리거나 떨어질때 마다 키 별로 할당된 값을 키보드컨트롤러로 전달하며, 이 값 을 스캔코드라고 한다.

 

키보드 컨트롤러의 출력버퍼에는 키보드 또는 마우스에서 수신된 데이터가 저장된다. 따라서 상태레지스터를 읽어서 출력버퍼에 데이터가 있는지 확인 후, 데이터가 있다면 출력버퍼를 읽어서 저장하면 된다.

 

 

if(kInPortByte(0x64)& 0x01)   //키데이터가있다면,

{

        returnkInPortByte(0x60);  //그값을리턴한다.

}

return0;     //값이없다면0으로

 

 

     

다음과 같이 어셈블러를 이용하여 해당 상태레지스터를 보고 그 데이터를 리턴 받아서 출력 하도록 한다.

 

    

 

while(1)

{

 key_value=KeyScancode();

 if(key_value!=0){     //키가눌러졌으면키의ASCII코드값을화면에출력

  kPrintStirng(0,15,key_value);

       }

}

 

 

다음과 같이 간단히 폴링 상태로키보드에서 입력을 받아 key데이터 즉 아스키 값을 출력을 할수  있다.

이렇게 만들어진 키 데이터는 가장 기본적인 방식으로 while루프안에서 폴링방식으로  체크를 한다.

 

이런방식은 키가 지속적으로 걸리면 다른 테스크에 무리를 준다.

따라서 중간 발표    때에는 가장 간단하게 테스크 하나를 통해서 지속적으로 Key값을 받아서 출력을 하였다.

 

하지만 이런 방식은 너무 비효율적 이므로 Keyboard인터럽트를 통해서 킷값을 받도록 한다.

     

     

(3)  Scan Code

 Keyboard는 키가 눌리거나 떨어질 때마다 해당 키에 대한 고유 코드를 전송하며, 키 이벤트에    대한 고유코드를 Scan Code라고 한다.

     

Scan Code

Key Name

Down Code

Up Code

Key Name

Down Code

Up Code

Esc

0x01

0x81

, <

0x33

0xB3

1 !

0x02

0x82

. >

0x34

0xB4

2 @

0x03

0x83

/ ?

0x35

0xB5

3 #

0x04

0x84

Right Shift

0x36

0xB6

4 $

0x05

0x85

Print Screen

0x37

0xB7

5 %

0x06

0x86

Alt

0x38

0xB8

6 ^

0x07

0x87

Space

0x39

0xB9

7 &

0x08

0x88

CAPS Lock

0x3A

0xBA

8 *

0x09

0x89

F1

0x3B

0xBB

9 (

0x0A

0x8A

F2

0x3C

0xBC

0 )

0x0B

0x8B

F3

0x3D

0xBD

- _

0x0C

0x8C

F4

0x3E

0xBE

= +

0x0D

0x8D

F5

0x3F

0xBF

BACK Space

0x0E

0x8E

F6

0x40

0xC0

Tab

0x0F

0x8F

F7

0x41

0xC1

Q

0x10

0x90

F8

0x42

0xC2

W

0x11

0x91

F9

0x43

0xC3

E

0x12

0x92

F10

0x44

0xC4

R

0x13

0x93

NUM Lock

0x45

0xC5

T

0x14

0x94

Scroll Lock

0x46

0xC6

Y

0x15

0x95

Home

0x47

0xC7

U

0x16

0x96

Up

0x48

0xC8

I

0x17

0x97

Page Up

0x49

0xC9

O

0x18

0x98

-

0x4A

0xCA

P

0x19

0x99

Left

0x4B

0xCB

[ {

0x1A

0x9A

Center

0x4C

0xCC

] }

0x1B

0x9B

Right

0x4D

0xCD

Enter

0x1C

0x9C

+

0x4E

0xCE

Ctrl

0x1D

0x9D

End

0x4F

0xCF

A

0x1E

0x9E

Down

0x50

0xD0

S

0x1F

0x9F

Page Down

0x51

0xD1

D

0x20

0xA0

Insert

0x52

0xD2

F

0x21

0xA1

Delete

0x53

0xD3

G

0x22

0xA2

F11

0x57

0xD7

H

0x23

0xA3

F12

0x58

0xD8

J

0x24

0xA4

Enter

0xE0 0x1C

0x9C

K

0x25

0xA5

Right Ctrl

0xE0 0x1D

0x9D

L

0x26

0xA6

/

0xE0 0x35

0xB5

 :

0x27

0xA7

Right Alt

0xE0 0x38

0xB8

‘ ““

0x28

0xA8

Home

0xE0 0x47

0xC7

` ~

0x29

0xA9

Up

0xE0 0x48

0xC8

Left Shift

0x2A

0xAA

Page Up

0xE0 0x49

0xC9

\ |

0x2B

0xAB

Left

0xE0 0x4B

0xCB

Z

0x2C

0xAC

Right

0xE0 0x4D

0xCD

X

0x2D

0xAD

End

0xE0 0x4F

0xCF

C

0x2E

0xAE

Down

0xE0 0x50

0xD0

V

0x2F

0xAF

Page Down

0xE0 0x51

0xD1

B

0x30

0xB0

Insert

0xE0 0x52

0xD2

N

0x31

0xB1

Delete

0xE0 0x53

0xD3

M

0x32

0xB2

Pause

0xE1 0x1D 0x45

-

 

     Keyboard의 Scan Code Table

     

 위 표와 같이 Keyboard의 모든 키는 각자의 고유 코드를 가지고 있으며, Keyboard는 키가 눌리거나 떨어질 때마다 그 상태에 해당하는 키 값을 Keyboard Controller로 전송한다.

Scan Code는 키가 눌렸을 때(Down)와 떨어졌을 때(Up)의 값이 다르며, 일반적으로 떨어졌을 때의 키 값은 눌러졌을 때의 값에 최상위 Bit(Bit 7)을 1로 설정한 값과 같다.

 

최상위 Bit를 1로 설정하는 것은 0x80을 더하는 것과 같으므로, 눌러졌을 때의 키 값에 0x80을 더하는 방식으로 처리하면 떨어졌을 때의 키 값을 가지고 있지 않아도 된다.

 

위 표에서 음영으로 표시한 부분은 확장 키  (Extended Key)의 Scan Code를 표시한 것이다. 확장 키는 AT PC 시절에 사용되었던  Keyboard 이후에 추가된 키를 의미한다. 확장 키는 일반적으로 QWERTY 키 영역과 숫자 패드 사이에 있다. 확장 키는 일반 키와 달리 2개 이상의 Code로 구성되므로 처리할 때 주의해야 한다.

 

확장 키는 다른 키와 달리 0xE0이나 0xE1로 시작한다는 공통점이 있으므로, 0xE0이나  0xE1에 해당하는 Scan Code가 수신되었을 때 이를 판단해서 처리하면 된다.

 

 Scan Code에서 ASCII Code로의 변환을 용이하게 하기 위해 Scan Code의 값을 Table Index로 사용하여 ASCII값을 구하는 변환 테이블을 만들어 사용하였다.

 변환과정에서 주의해야 할 사항은 조합 키의 상 태에 따라 영향을 받는 지의 여부와 확장 키를 처리하는 것이다.

     

     Scan Code를 ASCII Code로변환하는 알고리즘은 다음과 같다.

 

if( 마지막 키가 Pause여서 나머지 Scan Code 2개를 무시해야 하는가? )

{

 Scan Code를 무시

 종료

}     

if( Scan Code가 Pause의 첫 번째 코드(0xE1)인가? )

{

 나머지 Scan Code 2개를 무시하도록 설정하고 Pause 코드를 반환

 종료

}

else if( Scan Code가 확장 키의 첫 번째 코드(0xE0)인가? )

{

 다음에 수신될 키가 확장 코드임을 저장

 종료

}

     

if( Scan Code와 관계된 조함 키(Shift, Caps Lock, Num Lock)가 눌러졌는가? )

{

 Scan Code에 해당하는 ASCII 테이블의 조합 코드를 반환

}

else

{

 Scan Code에 해당하는 ASCII 테이블의 일반 코드를 반환

}     

if( 마지막 Scan Code가 확장 키의 첫 번째 코드(0xE0)였는가? )

{

 속성 값에 확장 키 옵션 반환

}     

조합 키(Shift, Caps Lock, Num Lock, Scroll Lock)의 눌림, 떨어짐 상태, LED 상태 갱신

종료

     

     

     

(4) Keyboard Interrupt Handler

 

 Keyboard Interrupt가 발생하면, I/O APIC Redirection Table Entry 1에 설정한 Vector값에 해당하는 IRQ(Interrupt Request)가 수행된다.

 

IRQ는 Interrupt가 수행되는 동안 다른 Interrupt가 방해하지 않도록 Timer Interrupt를   Disable한다. 이후, Keyboard  IRQ Handler 함수를 호출하여 필요한 작업을 수행한 뒤, EOI를 전달, Timer Interrupt를 Enable하고 IRQ를 종료한다.    

 

Keyboard의 입력 값은 포트 0x60의 출력 버퍼에 저장된다.

이 값은 Keyboard 각 자판의 Scan Code값이다. 이 버퍼의 값을 읽어 ASCII Code로 변환하여 OS 내에 있는 Keyboard Queue에  삽입한다.

 

 

 

* 모니터 드라이버

 

  화면에 문자를 출력하려면 현재 동작중인 화면모드와 관련된 비디오메모리의 어드레스를 알아야 한다.

 

비디오 메모리는 화면출력과 관계된 메모리로 모드 별로 정해진 형식에 따라 데이터를  채우면 화면에원하는 문자나 그림을 출력하는 구조로 구성되어 있다.  

 

PC부팅 후 기본으로 설정되는 화면모드는 텍스트모드로 화면크기는 가로80, 세로25 문자이며 비디오메모리어드레스는  0xB8000에서 시작한다.

 

또한, 화면에 표시하는 한 문자는 문자값 1바이트와 속성값1바이트로 구성되어 있다. 따라서 화면크기를 곱한 크기는 80*25*2=4000바이트이다.

      

 

텍스트모드 화면구조

 

     

  속성값은 하위4비트 전경색과 상위4비트 배경식으로 구별 된다. 각전경색과 배경색은 다시 최상위의 특수기능비트와 하위3비트의 색상으로 구분 된다. 전경색은 강조효과만 지원 하지만, 배경색은 강조와 깜빡임 두기능을 한다.

  전경색과 배경색의 최상위 비트를 모두 강조기능으로 사용하면 16가지 색상으로 표현할 수 있으므로 이를 이용하면 그럴듯 한 텍스트화면을 표현할 수 있으므로 사용하면 사용하도록 한다.

 

BIT

배경색(상위4비트)

전경색(하위4비트)

0~2

0x00

검은색

0x01

파란색

0x02

녹색

0x03

청색

0x04

빨간색

0x05

자홍색

0x06

노란색

0x07

흰색

3

0x00

효과없음

0x01

하위3비트색상에 깜빡임

효과를 주거나 강조 효과 추가

하위3비트색상에 깜빡임

효과를 주거나 강조 효과 추가

문자디바이스드라이버 속성치

이제 화면에 문자를 표시하려면 0xB8000어드레스에 문자와 속성 순서대로 지정하면 된다. 이를 이용하여 맨위에 ‘A’을 빨간색 배경에 밝은녹색으로 출력해 본다.

     

 mov ax, 0xB800  ;AX레지스터에0xB800복사

 mov ds, ax  ;DS세그먼트레지스터에AX레지스터의값(0xB800)을복사

     

 DS세그먼트레지스터에0xB800의값을설정했으니각가‘A’,0x4A를입력시켜준다.

     

 mov byte[0x00], 'A'

 mov byte[0x01], 0x4A     

 

 

 

커서는 모니터에 깜빡이는 ‘_’ 문자료 표시되며 입력된 텍스트가 출력될 위치를 표시하기 위해 사   용한다. 커서는 직접 ‘_’ 문자를 출력하여 표현하는 것이 아니라 모니터 출력을 담당하는 VGA 컨트롤러가 담당한다.

 

그 중 CRTC Controller Address Register와 CRTC Controller Data  Register가 담당하며 각 I/O Port 0x3D4와 0x3D5를 사용한다.

 

CRTC 컨트롤러 어드레스 레지 스터(0x3D4)는 CRTC의 내부 레지스터를 지정한다. 커서의 위치를 제어하려면 0xE와 0xF를 전달하여 상위 커서 위치 레지스터와 하위 커서 레지스터를 먼저 선택하고 CRTC 컨트롤러의 데이 터 레지스터(0x3D5)에 상위, 하위 바이트로 나누어 커서 위치를 전달하면 해당 위치로 커서가 이동하게 된다.

 

이때 CRT 컨트롤러는 컬럼과 라인 좌표가 아닌 비디오 메모리 내 오프셋을 사용한다.

 

 void SetCursor( int iX, int iY )

{

    int iLinearValue;

     

    iLinearValue = iY * CONSOLE_WIDTH + iX; // Calculate Offset

     

    // Send 0x0E to CRTC(0x3D4), Select upperbyte

    outportb( VGA_PORT_INDEX, VGA_INDEX_UPPERCURSOR );

    outportb( VGA_PORT_DATA, iLinearValue >> 8 );

     

    // Send 0x0F to CRTC(0x3D4), select lowwerbyte

    outportb( VGA_PORT_INDEX, VGA_INDEX_LOWERCURSOR );

    outportb( VGA_PORT_DATA, iLinearValue & 0xFF );

 gs_stConsoleManager.iCurrentPrintOffset = iLinearValue; // update offset

}

     

void GetCursor( int *piX, int *piY )

{

    *piX = gs_stConsoleManager.iCurrentPrintOffset % CONSOLE_WIDTH;

    *piY = gs_stConsoleManager.iCurrentPrintOffset / CONSOLE_WIDTH;

} // CONSOLE_WIDTH == 80

 

 

필요성 : 폴링 방식은 프로세서가 키보드 컨트롤러를 주기적으로 확인하므로 프로세서의 소모가 심하고 확인하는 주기에 비례하여 데이터가 수신되는 시간이 길어지는 문제점이 있다.

 

인터럽트 방식은 컨트롤러에 데이터가 있거나 데이터를 전송할 수 있을 때 인터럽트를 통해 이를 알려주므   로 상대적으로 프로세서를 덜 사용하게 된다.

 

이런 차이는 멀티태스킹 환경에서 더욱 확연히 드러날 것이다. 그래서 최종적으로 키보드 디바이스를 인터럽트 방식으로 변경하려면 버퍼는 필수적으로 필요하게 된다.

왜냐하면 인터럽트는 발생 시점을 예측할 수가 없어 수신된 키 값을 온전히 전달하기가 어렵기 때문이다.