linux io_uring - ghdrako/doc_snipets GitHub Wiki

io_uring to nowoczesny interfejs asynchronicznego I/O w Linuxie,który pozwala na wykonywanie operacji wejścia/wyjścia (czytanie, pisanie, sockety, itd.) bez przełączania kontekstu między przestrzenią użytkownika a jądrem.

Został wprowadzony w Linux 5.1 (2019) przez Jensa Axboe (twórcę m.in. fio i blk-mq).

Tradycyjnie, każda operacja I/O w Linuxie wygląda tak:

[User space]  →  syscall (read/write)  →  [Kernel space] →  wykonanie → powrót

ażde takie przejście = context switch, który kosztuje tysiące cykli CPU. W aplikacjach o dużym I/O (serwery, bazy danych, proxy, load balancery) to ogromny narzut.

Wcześniej istniały:

  • select(), poll(), epoll() — obsługa zdarzeń, ale nie danych,
  • AIO (POSIX async I/O) — powolne, toporne, mało elastyczne.

io_uring to nowy, wydajny model I/O, który eliminuje ten koszt.

Zamiast syscali — dwa pierścienie (rings) współdzielone między jądrem a procesem:

+----------------------------+
| User Space (aplikacja)     |
|                            |
|  [ Submission Queue (SQ) ] |  → zgłaszasz operacje do wykonania
|  [ Completion Queue (CQ) ] |  ← odbierasz informacje o zakończeniu
+----------------------------+
             ↑  ↓
   współdzielona pamięć (shm)
             ↑  ↓
+----------------------------+
| Kernel Space (io_uring)    |
+----------------------------+

Aplikacja:

  1. Wrzuca do Submission Queue (SQ) zadania, np.:
  2. “odczytaj 4 KB z tego pliku od offsetu X”
  3. “zapisz dane do socketu”
  4. Kernel przetwarza te operacje asynchronicznie.
  5. Gdy są gotowe — zapisuje wyniki do Completion Queue (CQ).

Aplikacja tylko odczytuje wyniki, bez syscalli.

struct io_uring ring;
io_uring_queue_init(32, &ring, 0); // inicjalizacja

struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
io_uring_prep_read(sqe, fd, buf, len, offset);
io_uring_submit(&ring); // wysłanie do kernela

struct io_uring_cqe *cqe;
io_uring_wait_cqe(&ring, &cqe);
printf("odczytano %d bajtów\n", cqe->res);
io_uring_cqe_seen(&ring, cqe);