버티의 블로그
[운영체제 #06] I/O Systems 본문
I/O Mapping
I/O Mapping은 CPU가 I/O 장치와 통신하는 매커니즘인데, I/O 장치의 주소를 할당하는 방식에 따라 2가지로 나뉜다.
- Memory-mapped I/O : I/O 장치들이 CPU의 메모리 공간 내에 같이 매핑된다.
- I/O-mapped I/O : I/O 장치들이 메모리와 서로 다른 주소 공간에 매핑된다.
Protocol for Interaction between CPU and Controller
CPU는 입출력 작업의 진행 상태를 관리하여 시스템 리소스를 효율적으로 사용해야 하기 때문에 I/O(Device) Controller의 상태를 모니터링할 필요가 있다. 이에 2가지 방법이 존재한다. 식당에서 벨을 누르는 예시로 간단히 설명하자면, 누가 눌렀는지 직원이 직접 확인하는 방식이 Polling, 누른 테이블 번호가 전광판에 표시되는 방식이 Interrupt 방식이다.
1. Polling or Busy-waiting
이 방식은 CPU가 I/O controller에게 "너의 I/O device는 작업이 끝났니?"하고 계속 물어보는 느낌이라 보면 된다. I/O controller가 작업 상태일 때 busy bit라는 값이 설정되는데, 이 비트가 clear될때까지 반복적으로 busy bit를 확인한다. 물론 이 방법은 controller와 device가 빠른 경우 합리적일 수 있겠지만, 그렇지 않은 경우가 발생하여 busy-waiting이 길어지면 다른 작업도 해야하는 CPU입장에서는 손해이다. 따라서 이 방법은 보통 비효율적이라고 여겨진다.
2. Vectored Interrupt
이 방식은 I/O controller가 CPU에게 스스로 상태를 보고한다고 생각하면 된다. 각 I/O device들은 고유의 인터럽트 벡터 값을 갖고 있는데, I/O device의 작업이 완료되면 I/O controller가 완료된 device의 벡터값을 "인터럽트"라는 신호로 CPU에게 전송한다. 이는 CPU가 인터럽트를 빠르게 발견하고 처리할 수 있기 때문에 효율적이고 응답 시간이 빠르지만, 구현이 복잡하고 더 많은 리소스를 요구한다.
그럼 CPU는 어떻게 하던 작업을 중단하고 인터럽트를 찾아 해결할까?
인터럽트를 인지하면 CPU는 하던 작업을 중단하고 즉시 Interrupt service routine(ISR)이 실행되는데, CPU는 이곳에 현재 상태를 저장한다. ISR은 CPU 레지스터와 PC값을 보관하여 이후 원래 작업으로 복귀할 수 있도록 돕는다. ISR의 대응을 마치면 Interrupt handler가 실행되는데, 보통 ISR에 의해 호출되거나 ISR로부터 정보를 전달받아 실행된다. Interrupt handler는 인터럽트의 원인을 처리하는데 초점을 맞추며, 이에 인터럽트 유형에 맞는 필요한 작업을 결정하고 수행한다. 이후 CPU는 중단한 작업을 재개한다.
Direct Memory Access (DMA)
DMA는 CPU의 개입 없이 메모리와 디바이스 사이에서 데이터 전송을 하는 방식으로, 주로 많은 데이터를 빠른 속도로 전송하기를 원하는 I/O 장치에서 사용한다. DMA를 사용하면 CPU가 다른 task에 집중할 수 있게 되어 데이터 전송의 지연이 감소하고, 블록 단위로 데이터를 전송하기 때문에 더 많은 데이터를 전송할 수 있다.
이러한 DMA의 대표적인 기법으로 Cycle stealing이 있는데, 이는 DMA 컨트롤러가 CPU로부터 Bus를 가져와 데이터 전송을 수행하는 방법이다. CPU가 메모리 전송 작업을 DMA에게 위임한 것으로도 볼 수 있으며, Cycle stealing이 진행되는 도중에 CPU는 메모리 접근이 필요없는 작업을 수행한다. 그래서 CPU 부하가 낮아지고 보다 효율적인 데이터 전송이 가능해진다.
Buffering
버퍼링은 두 장치 또는 장치와 어플리케이션 간의 데이터를 전송하는 동안 데이터를 메모리에 저장하는 것을 의미하는데, 버퍼링이 필요한 이유는 다음과 같다.
- 장치 간 속도 불일치를 대처하기 위해
- 장치의 전송 크기 불일치를 대처하기 위해
- 데이터를 produce하고 comsume하는 시간 차이를 대처하기 위해
- "copy semantics"를 유지하기 위해 : 데이터가 특정 버전으로 유지되는 것을 보장
더블 버퍼링은 2개의 버퍼를 사용하는데, Input device에서 데이터가 지속적으로 들어올 때, 한 버퍼를 사용하여 현재 데이터를 처리하고 동시에 다른 버퍼로 새로운 데이터를 수신하는 방식이다. 그래서 데이터 수신과 처리 간의 지연 시간을 최소화시킬 수 있는 방법이다. 더블 버퍼링에서 사용하는 버퍼들로 Application buffer과 Kernel buffer가 있는데, 이를 소켓 통신의 예시로 설명하겠다.
유저가 소켓을 송신할 때는 application buffer가 네트워크를 통해 전송할 데이터를 저장했다가 "write" system call을 통해 데이터가 kernel buffer로 복사된다. 그럼 커널은 나중에 이 데이터를 네트워크로 전송한다.
반대로 유저가 소켓을 수신할 때는 네트워크로부터 오는 데이터를 먼저 kernel buffer로 수신하여 저장하고, 유저 측에서 "read" system call이 발생할 때 데이터를 application buffer로 복사한다.
'OS_NW > 운영체제' 카테고리의 다른 글
[운영체제 #08] Synchornization Tools (0) | 2024.05.09 |
---|---|
[운영체제 #07] CPU Scheduling (1) | 2024.04.30 |
[운영체제 #05] Computer System Operation (0) | 2024.04.18 |
[운영체제 #04] Threads (0) | 2024.04.16 |
[운영체제 #03] Interprocess Communication (0) | 2024.04.09 |