vmsplice(2)
Splice user-space pages directly into a pipe; with SPLICE_F_GIFT the kernel takes ownership of those pages without copying.
- Since
- Linux 2.6.17check your kernel →
- glibc
- glibc 2.5
- System
- Linux
- Man page
- vmsplice(2)
Synopsis
#include <fcntl.h>
#include <sys/uio.h>
ssize_t vmsplice(int fd, const struct iovec *iov,
size_t nr_segs, unsigned int flags);Rod's take
vmsplice(2) is the user-to-kernel on-ramp for the splice/tee pipeline. With SPLICE_F_GIFT and page-aligned buffers, the kernel remaps your pages into the pipe without a copy; chain with splice(2) to land them in a file or socket. Without GIFT, it copies anyway. The page-alignment requirement is not advisory: misaligned buffers silently fall back to copy with no error. Useful above ~32 KB per call on high-throughput write paths; below that the pipe overhead exceeds the copy savings.
Flags and arguments that matter
| Name | What it does |
|---|---|
| SPLICE_F_GIFT | Transfer page ownership to the kernel; no copy is made. The caller must never modify those pages again. Buffers must be page-aligned and lengths page-size multiples, or the kernel silently falls back to copying. |
| SPLICE_F_MOVE | Hint to move rather than copy kernel pages when the pipe data is later read. Has been a no-op since Linux 2.6.21 in most code paths; harmless to pass. |
| SPLICE_F_NONBLOCK | Do not block on the pipe; fail with EAGAIN if the pipe buffer is full. |
Errors you will actually hit
| errno | Meaning |
|---|---|
| EBADF | fd is not a valid write end of a pipe. |
| EINVAL | fd is not a pipe write end, or nr_segs exceeds IOV_MAX. |
| EAGAIN | SPLICE_F_NONBLOCK was set and the pipe buffer is full. |
Example
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/uio.h>
#include <unistd.h>
int pfd[2];
pipe(pfd);
void *buf = mmap(NULL, 4096, PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0);
/* fill buf */
struct iovec iov = { buf, 4096 };
ssize_t n = vmsplice(pfd[1], &iov, 1, SPLICE_F_GIFT);
/* buf is now owned by the kernel; do not touch it */
splice(pfd[0], NULL, out_fd, NULL, n, 0);Trimmed from the full walkthrough in vmsplice(2): give the kernel your pages, skip the copy.
BSD equivalent
No equivalent. FreeBSD covers the user-memory-to-socket path with sendfile(2) (FreeBSD 3.1). For user-memory-to-pipe there is only write()/writev(); the splice family is Linux-specific.
The long version, from the console
Sources
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
