io_uring_0103
IO_URING 저수준 인터페이스
IO_URING 저수준 인터페이스
이전 세션에서 언급했듯이, 심각한 프로그램에서 저수준 io_uring API를 사용할 가능성은 낮습니다. 하지만 실제로 어떤 종류의 io_uring 인터페이스가 표시되는지 아는 것은 항상 좋은 생각입니다. 이를 위해 공유 링 버퍼와 관련 시스템 호출을 통해 프로그램에 직접 표시되는 io_uring 인터페이스를 조작해야 합니다. 좋은 예제이자 간단한 예제를 통해 이 인터페이스를 잘 표현할 수 있습니다. 이를 위해 여기에서는 Unix cat 유틸리티를 에뮬레이션하는 예제를 제시합니다. 간단하게 하기 위해 한 번에 하나의 작업을 io_uring 표시하고, 작업이 완료될 때까지 기다렸다가 다음 작업을 표시하는 프로그램을 만들어 보겠습니다. 실제 프로그램에서는 동기/차단 호출을 사용하여 이러한 방식으로 작업을 수행할 수도 있지만, 이 프로그램의 주요 목표는 다른 프로그램 로직의 방해 없이 io_uring 인터페이스에 익숙해지는 것입니다.
📦 Familiarity with the readv(2) system call - readv(2) 시스템 호출 에 대한 익숙함
이 예제를 잘 이해하려면 readv(2) 시스템 호출에 익숙해야 합니다.
아직 익숙하지 않으시다면, 좀 더 쉬운 소개 부분을 읽어보신 후 여기로 돌아와서 계속 진행하시기 바랍니다.
io_uring by example: Part 1 – Introduction
📦 Introduction to the low-level interface - 저수준 인터페이스 소개
io_uring의 인터페이스는 간단합니다. 제출(submission) 큐와 완료(completion) 큐가 있습니다.
제출 큐에서 완료하려는 다양한 작업에 대한 정보를 제출합니다.
예를 들어, 현재 프로그램에서 readv(2)로 파일을 읽으려고 하므로 제출 큐 항목(SQE:submission queue entry)의 일부로
설명하는 제출 큐 요청을 배치합니다.
또한 여러 요청을 배치할 수 있습니다.
큐 깊이(정의할 수 있음)가 허용하는 한 많은 요청을 배치할 수 있습니다.
이러한 작업은 읽기, 쓰기 등을 혼합할 수 있습니다.
그런 다음 io_uring_enter() 시스템 호출을 호출하여 커널에 제출 큐에 요청을 추가했음을 알립니다.
그런 다음 커널은 주짓수(jujitsu)를 수행하고 해당 요청 처리를 마치면 CQE(completion queue entry) 또는
각 해당 SQE에 대한 완료 큐 항목의 일부로 결과를 완료 큐에 배치합니다.
이러한 CQE는 커널과 사용자 공간에서 공유하는 버퍼에 배치되므로 사용자 공간에서 즉시 액세스할 수 있습니다.
앞서 이 io_uring 특정 장점에 대해 다루었지만, 눈치 빠른 독자라면 여러 I/O 요청으로 큐를 채운 후 각 I/O 요청에 대해
하나의 시스템 호출을 하는 것보다 단일 시스템 호출을 하는 이 인터페이스가 훨씬 효율적이라는 것을 이미 알아차렸을 것입니다.
효율성을 한 단계 더 높이기 위해 'io_uring'은 사용자가 'io_uring_enter()'를 호출하여 커널에
새로운 제출 대기열 항목을 알리지 않고도 커널이 사용자가 제출 대기열에 만든 항목을 폴링하는 모드를 지원합니다.
또 다른 주목할 점은 스펙터와 멜트다운 하드웨어 취약점이 발견되고 운영 체제에서 해결책을 마련한 이후,
시스템 호출 비용이 그 어느 때보다 높아졌다는 것입니다.
따라서 고성능 애플리케이션의 경우 시스템 호출 수를 줄이는 것은 매우 중요합니다.
이 작업을 수행하기 전에 큐를 설정해야 합니다. 큐는 특정 깊이/길이를 가진 링 버퍼입니다.
이 작업을 수행하려면 'io_uring_setup()' 시스템 호출을 호출합니다.
제출 큐 항목을 링 버퍼에 추가하고 완료 큐 링 버퍼에서 완료 큐 항목을 읽어서 실제 작업을 수행합니다.
이는 io_uring 인터페이스의 설계 방식에 대한 개요입니다.
