$RodHat_
Syscall reference · IPC

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

NameWhat it does
SPLICE_F_GIFTTransfer 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_MOVEHint 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_NONBLOCKDo not block on the pipe; fail with EAGAIN if the pipe buffer is full.

Errors you will actually hit

errnoMeaning
EBADFfd is not a valid write end of a pipe.
EINVALfd is not a pipe write end, or nr_segs exceeds IOV_MAX.
EAGAINSPLICE_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

  1. vmsplice(2), man7.org
  2. Splice: A System Call for Pipes, LWN.net

Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.