Fundamentals 11 min read

How Linux Zero‑Copy I/O Works: mmap, sendfile, splice & tee Explained

The article explains Linux zero‑copy I/O techniques—mmap, sendfile, splice, and tee—detailing their design principles, execution flows, context‑switch and data‑copy reductions, advantages, limitations, and appropriate use cases, helping developers choose the optimal method for high‑performance file and network transfers.

Liangxu Linux
Liangxu Linux
Liangxu Linux
How Linux Zero‑Copy I/O Works: mmap, sendfile, splice & tee Explained

Traditional file I/O that reads a file and sends it through a socket requires four context switches, two CPU‑to‑memory copies and two DMA copies.

Zero‑Copy Strategies in Linux

Performance can be improved by reducing data copies and context switches. Linux provides four mechanisms— mmap , sendfile , splice and tee —each lowering the number of copies or switches.

mmap (Memory‑mapped I/O)

Virtual memory abstracts physical memory via page tables. Each process has its own page table; when a page is accessed and not present, a page‑fault triggers allocation. mmap maps the same physical page into both user‑space and kernel‑space, allowing the user process to operate directly on the data without copying between the two spaces.

Execution flow:

User process calls mmap, causing the first context switch and creating a kernel buffer.

A page‑fault occurs; the CPU notifies the DMA controller to read data.

DMA copies data into physical memory and establishes the kernel‑buffer‑to‑physical‑memory mapping.

The kernel maps the user‑space buffer to the same physical page, causing the second context switch back to user space.

User process processes data and calls send, causing a third context switch.

The kernel creates a network buffer and copies data from the kernel read buffer.

DMA sends the network buffer to the NIC, returning control to user space with a fourth context switch.

Summary

Eliminates two user‑kernel CPU copies but adds one extra kernel‑space copy, netting a reduction of one CPU copy.

Best for large files; small files may cause memory fragmentation.

If another process accesses the mapped file, illegal access can raise a SIGBUS.

sendfile

Introduced in Linux 2.1, sendfile transfers data from a file descriptor to a socket with only two context switches, one kernel‑space CPU copy and two DMA copies.

ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

Parameters: out_fd – socket descriptor, in_fd – file descriptor, offset – optional file offset, count – number of bytes.

User calls sendfile, first context switch to kernel.

CPU instructs DMA to copy file data into a kernel buffer.

Kernel copies data from its buffer to the network buffer.

CPU tells DMA to transmit the network buffer.

System call returns, second context switch back to user space.

Summary

Only two context switches, one CPU copy, two DMA copies – a true zero‑copy for the data path.

Data cannot be modified during transfer.

sendfile with DMA Gather

Linux 2.4 added DMA gather support: the kernel stores the file’s memory address and offset in the network buffer, allowing DMA to fetch directly from the file buffer without an intermediate copy.

User calls sendfile, first context switch.

CPU copies file data to a kernel buffer.

Kernel stores the buffer’s address and parameters as a descriptor in the network buffer.

DMA reads the descriptor and transfers data directly to the NIC.

System call returns, second context switch.

Summary

Requires DMA‑capable hardware.

Achieves 0 CPU copies, 2 DMA copies, and only 2 context switches – genuine zero‑copy.

Data remains read‑only.

splice

Added in Linux 2.6.17 to overcome sendfile’s limitations, splice creates a pipe between a file descriptor and a socket, moving data through kernel buffers without user‑space copies.

ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);

User calls splice, first context switch.

CPU tells DMA to copy file data into a kernel buffer.

A pipe is established between the kernel buffer and the network buffer.

DMA reads from the pipe and sends data to the NIC.

System call returns, second context switch.

Summary

2 context switches, 0 CPU copies, 2 DMA copies – true zero‑copy.

Data cannot be altered during transfer.

Either fd_in or fd_out must be a pipe.

tee

tee

works like splice but both ends of the operation must be pipes, allowing duplication of data streams without copying.

Overall Comparison

All four mechanisms reduce context switches and data copies compared with traditional I/O. mmap is suited for large files but may cause fragmentation; sendfile offers the simplest zero‑copy for file‑to‑socket transfers; sendfile + DMA gather and splice achieve genuine zero‑copy with hardware support; tee is useful for duplicating pipe streams.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

I/OLinuxmmapsendfileZero CopyTEEsplice
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

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.