운영 체제의 바이블 Operating System Concepts(흔히 공룡책🦕이라고들 하죠)을 바탕으로 I/O 시스템에 대해 정리해보았습니다.

목차

  1. 1. I/O가 대체 뭐지?
  2. 2. I/O 요청은 어떻게 처리되는 걸까?
  3. 3. 로컬 PC의 키보드 입력을 원격지 PC로 전달하는 과정
  4. 4. I/O에 대해 정리해보면
  5. 5. I/O를 좀 더 효율적으로 처리하기 위해서는?
  6. 6. 마치며

I/O가 대체 뭐지?

컴퓨터는 크게 2가지 역할을 수행한다고 볼 수 있는데 하나는 연산(computing) 이고, 하나는 I/O 즉, 입출력을 처리하는 것입니다. 대부분의 경우 컴퓨터의 주요한 역할은 입출력은 처리하는 I/O라고 생각하면 됩니다. (우리가 웹 페이지에 접속한다거나 파일을 편집하거나 또는 어떠한 정보를 읽거나 입력하고자 할 때 엄청난 연산이 일어나지는 않죠?)
컴퓨터에서 운영 체제는 이러한 입출력에 대한 수행과 물리적인 입출력 장치(하드웨어)를 관리하고 컨트롤해주고 있습니다. 그렇다면 (키보드의 입력과 같은) 하드웨어가 주는 입출력 신호를 어떻게 내 PC에 있는 프로그램이 전달받아 처리할 수 있는 걸까요?


I/O 요청은 어떻게 처리되는 걸까?

공룡책🦕의 내용을 바탕으로 I/O 요청이 처리되는 과정을 하나씩 알아보도록 하겠습니다.

  1. 사용자 프로세스는 열고 있던 파일의 파일 디스크립터(fd)를 통해 blocking 함수인 read()를 호출(시스템 콜)합니다.
  2. 커널 내부의 시스템 콜 코드에서는 정확성을 위해 파라미터들을 체크합니다. 입력 값인 경우에는 해당 데이터가 이미 버퍼 캐시에 존재하여 접근이 가능한 상태라면 그 데이터는 사용자 프로세스로 곧장 반환되고 I/O 요청은 완료됩니다.
  3. 만약 버퍼 캐시에 데이터가 없는 상태라면 물리적인 I/O가 반드시 수행되어야 합니다. 시스템 콜을 요청한 사용자 프로세스는 실행 큐(run queue)에서 삭제되고 대기 큐(wait queue)에 추가됩니다. 그리고나서 시스템 콜에 의한 I/O 작업 요청이 스케줄에 포함됩니다. 궁극적으로 I/O 서브 시스템이 해당 요청을 디바이스 드라이버로 전달합니다. I/O 작업 요청이 디바이스 드라이버로 전달되는 방식은 운영 체제의 종류에 따라 subroutine call이 될 수도 있고, in-kernel message가 될 수도 있습니다.
  4. 디바이스 드라이버는 커널 버퍼 공간을 할당받아 데이터를 수신할 준비를 하고 I/O 스케줄을 처리합니다. 궁극적으로 디바이스 드라이버는 디바이스 컨트롤 레지스터를 통해서 디바이스 컨트롤러에게 실제 커맨드를 전달합니다.
  5. 디바이스 컨트롤러는 데이터 전송을 수행하기 위해 디바이스 하드웨어를 동작시킵니다. 여기까지가 사용자 프로세스에서의 I/O 요청이 실제 하드웨어까지 도달하는 과정입니다😁
  6. 지금 보고 있는 예시의 경우에 (디바이스로 I/O 요청 전송이 완료된 경우 인터럽트를 발생시키는)DMA 컨트롤러가 전송 과정을 관리한다고 가정해봅시다.
  7. 인터럽트 벡터 테이블을 참조하여 해당 인터럽트 신호가 적절한 인터럽트 핸들러에게 전달되고, 해당 인터럽트 핸들러는 필요한 모든 정보를 저장하고 디바이스 드라이버로 신호를 전달합니다.
  8. 디바이스 드라이버가 완료된 I/O 요청 상태를 결정하고 커널 I/O 서브 시스템에게 전달된 요청 정보 처리가 완료됐다고 알려줍니다.
  9. 커널은 디바이스 드라이버로부터 전달받은 데이터를 전송하고 사용자 프로세스의 주소 공간에 코드를 반환합니다. 그리고나서 사용자 프로세스는 대기 큐(wait queue)에서 준비 큐(ready queue)로 이동하게 됩니다.
  10. 사용자 프로세스를 준비 큐(ready queue)로 이동시키는 작업은 해당 사용자 프로세스의 blocking 상태를 풀겠다는 의미입니다. 스케줄러는 사용자 프로세스를 다시 CPU에 할당하고 시스템 콜이 완료되는 시점에 사용자 프로세스는 실행 상태로 재개됩니다.

로컬 PC의 키보드 입력을 원격지 PC로 전달하는 과정

공룡책🦕에서 가져온 예시를 통해 키보드로 부터 들어온 입력 신호가 어떻게 내 PC의 프로그램으로 전달되는지, 더 나아가 전달받은 키보드 입력을 어떻게 멀리 떨어진 원격지 PC에 전달할 수 있는지 살펴보겠습니다.

네트워크 트래픽 또한 높은 컨텍스트 스위치 비율의 원인이 될 수 있습니다. 한 장비에서 또 다른 장비로 원격 로그인을 하는 상황을 예로 들어 보겠습니다. 로컬 장비에서 입력 되는 각각의 문자들은 원격지 장비로 전달돼야 합니다. 로컬 장비에서의 상황을 보면 문자가 입력되고; 키보드 인터럽트가 발생하며; 입력된 문자는 인터럽트 핸들러와 디바이스 드라이버, 커널을 차례대로 통과하여 사용자 프로세스에 도달합니다. 사용자 프로세스는 원격지 장비에 문자를 전송하기 위해 네트워크 I/O 시스템 콜을 사용합니다.

Network traffic can also cause a high context-switch rate. Consider, for instance, a remote login from one machine to another. Each character typed on the local machine must be transported to the remote machine. On the local machine, the character is typed; a keyboard interrupt is generated; and the character is passed through the interrupt handler to the device driver, to the kernel, and then to the user process. The user process issues a network I/O system call to send the character to the remote machine.

이후 입력된 문자는 네트워크 패킷을 생성하는 네트워크 레이어를 통해 로컬 커널에서 네트워크 디바이스 드라이버로 흘러 들어갑니다. 네트워크 디바이스 드라이버는 전송할 문자가 포함된 네트워크 패킷을 네트워크 컨트롤러에게 전달하며 이 과정에서 문자가 전송되고 인터럽트가 발생하게 됩니다. 인터럽트는 커널을 통해 사용자 프로세스로 다시 돌아가게 되는데 이는 네트워크 I/O 시스템 콜이 완료되었음을 사용자 프로세스에 알리기 위함입니다.

The character then flows into the local kernel, through the network layers that construct a network packet, and into the network device driver. The network device driver transfers the packet to the network controller, which sends the character and generates an interrupt. The interrupt is passed back up through the kernel to cause the network I/O system call to complete.

이제 원격지 시스템(위 그림의 receiving system)의 네트워크 하드웨어는 (위 그림의 sending system에서 전송한)패킷을 수신하며 패킷 수신에 대한 인터럽트가 발생됩니다. 전송된 문자는 네트워크 프로토콜을 통해 언패키징되고 적절한 네트워크 데몬으로 전달됩니다. 네트워크 데몬은 이 전송과 관련된 원격지 장비의 로그인 세션을 확인하여 해당 서브 데몬으로 패킷을 전달합니다. 이러한 과정에서 컨텍스트 스위치와 스테이트 스위치가 수반됩니다 (Figure 12.16).

Now, the remote system’s network hardware receives the packet, and an interrupt is generated. The character is unpacked from the network protocols and is given to the appropriate network daemon. The network daemon identifies which remote login session is involved and passes the packet to the appropriate subdaemon for that session. Throughout this flow, there are context switches and state switches (Figure 12.16).


I/O에 대해 정리해보면

I/O란 하드웨어 장치를 통한 입출력 정보를 컴퓨터에서 구동 중인 어플리케이션에서 컨트롤하고자 할 때 사용하는 일종의 인터페이스라고 생각하시면 됩니다.

I/O 시스템 콜은 물리적인 장치와 사용자 프로세스 사이의 많은 소프트웨어 계층을 오가는 일이기 때문에 CPU 사용 측면에서 비용이 많이 드는 작업이기도 합니다. 이 둘 간에 존재하는 계층들은 커널의 보호 경계를 오가며 발생하는 컨텍스트 스위칭이나 I/O 장치를 서비스하기 위한 시그널링이나 인터럽트 핸들링, 커널 버퍼와 사용자 프로세스간의 데이터 복사 과정에서의 CPU나 메모리 시스템의 부하로부터 발생하는 일종의 오버헤드입니다.

I/O system calls are costly in terms of CPU consumption because of the many layers of software between a physical device and an application. These layers imply overhead from several sources: context switching to cross the kernel’s protection boundary, signal and interrupt handling to service the I/O devices, and the load on the CPU and memory system to copy data between kernel buffers and application space.


I/O를 좀 더 효율적으로 처리하기 위해서는?

I/O 처리 과정의 효율성을 높이기 위한 몇가지 이론적인 가이드라인이 있습니다.

  1. 컨텍스트 스위치의 횟수를 줄인다.
  2. 디바이스 장치와 어플리케이션 간의 데이터 교환 과정에서 반드시 수행돼야 하는 메모리 상의 데이터 복사 횟수를 줄인다.
  3. 대용량 전송, 스마트 컨트롤, 폴링을 사용함으로써 인터럽트의 빈도를 줄인다.
  4. CPU에서 발생하는 단순 데이터 복사 작업을 줄이기 위해 DMA-knowledgable 컨트롤러를 사용하거나 채널을 사용함으로써 동시성을 높인다.
  5. 디바이스 컨트롤러에서의 작업을 CPU와 Bus에서의 작업과 동시에 처리하기 위해 I/O의 기본적인 처리는 하드웨어로 이관한다.
  6. CPU, 메모리 서브시스템, Bus, I/O 수행간(이들 중 어느 한쪽에 일이 몰린다는건 다른 쪽은 노는 시간이 발생한다는 의미)의 밸런스를 맞춘다.

마치며

지금까지 공룡책🦕을 바탕으로 I/O 시스템에 대해 간략히 정리해보는 시간을 가졌습니다. I/O 처리 단계별로 좀 더 세부적인 동작 방식을 알고 싶다면 아래 레퍼런스를 참고하시기 바랍니다.



해당 게시글에서 발생한 오탈자나 잘못된 내용에 대한 정정 댓글 격하게 환영합니다😎

Reference

  • Abraham Silberschatz, Greg Gagne, Peter B. Galvin. (2018). Operating System Concepts, 10th Edition. Wiley