Fundamentals 20 min read

Linux I/O Models and io_uring Performance Overview

Linux I/O models range from synchronous native operations to asynchronous kernel‑bypass techniques, with APIs such as open, read, write, mmap, sendfile and splice, while the modern io_uring interface—supporting interrupt, polling, and kernel‑polling modes via liburing—delivers superior performance, especially at high queue depths, compared to traditional libaio.

DeWu Technology
DeWu Technology
DeWu Technology
Linux I/O Models and io_uring Performance Overview

Linux I/O models are classified into native I/O, kernel bypass, etc. Native I/O includes synchronous and asynchronous operations. Synchronous I/O blocks the calling process until the operation completes, while asynchronous I/O allows the process to continue.

Blocking refers to the process state when a system call puts the process to sleep until the requested event occurs.

Common file operation APIs:

#include
#include
#include
#include
//  返回值:成功返回新分配的文件描述符,出错返回-1并设置errno
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

// 返回值:成功返回0,出错返回-1并设置errno
int close(int fd);

// 返回值:成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0
ssize_t read(int fd, void *buf, size_t count);

// 返回值:成功返回写入的字节数,出错返回-1并设置errno
ssize_t write(int fd, const void *buf, size_t count);

Typical open flags include O_CREAT, O_EXCL, O_TRUNC, O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, O_NONBLOCK, O_SYNC, O_DIRECT.

Mmap maps a file into the process address space, allowing direct memory access to file data.

// 成功执行时,mmap()返回被映射区的指针。失败时,mmap()返回MAP_FAILED[其值为(void *)-1]
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

// 成功执行时,munmap()返回0。失败时,munmap返回-1,error返回标志和mmap一致;
int munmap(void *addr, size_t len);

// 将内存中的修改同步到磁盘
int msync(void *addr, size_t len, int flags);

Direct I/O (O_DIRECT) bypasses the kernel page cache, reducing data copies.

sendfile transfers data from a file descriptor to a socket without copying to user space.

splice connects two file descriptors, allowing data movement without user‑space copies; it is a superset of sendfile.

io_uring is a modern Linux asynchronous I/O interface that supports both storage and network I/O. It uses submission (SQ) and completion (CQ) queues.

Key io_uring system calls:

int io_uring_setup(u32 entries, struct io_uring_params *p);
int io_uring_register(unsigned int fd, unsigned int opcode, void *arg, unsigned int nr_args);
int io_uring_enter(unsigned int fd, unsigned int to_submit, unsigned int min_complete, unsigned int flags, sigset_t *sig);

io_uring operates in three modes: interrupt‑driven (default), polling, and kernel‑polling. Polling reduces latency at the cost of CPU usage; kernel‑polling uses a kernel thread to submit and reap I/O without user‑space syscalls.

liburing provides a convenient wrapper around io_uring. Example initialization, submission, and completion handling are shown in the source code.

Performance comparisons show that io_uring outperforms traditional libaio in polling mode and approaches the performance of SPDK at high queue depths, while its advantage over libaio in non‑polling mode is modest.

Conclusion: io_uring offers a high‑performance, flexible I/O solution for Linux, though it requires recent kernel versions.

performanceI/Oio_uringLinuxsystem programming
DeWu Technology
Written by

DeWu Technology

A platform for sharing and discussing tech knowledge, guiding you toward the cloud of technology.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.