Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

sendfile(2)

FieldValue
Numbers (x64 / i386 / arm64-generic / arm32)sendfile 40 / 187 / 71 / 187; sendfile64 - / 239 / - / 239 (per-call table below)
Since (kernel)sendfile 2.2; sendfile64 2.6 (<sys/sendfile.h> present since glibc 2.1)
Man pageman2/sendfile.2 (sendfile64.2 is an .so alias of it)
glibc wrappersendfile() declared in <sys/sendfile.h>; host glibc 2.41 exports sendfile@@GLIBC_2.2.5 (nm -D); the glibc sendfile() wrapper transparently deals with the sendfile/sendfile64 kernel difference (man2/sendfile.2 NOTES)
Aliases coveredsendfile64
Ledger IDSC-sendfile, SC-sendfile64

Numbers by call, from the ledger and cross-checked against the cached kernel tables (syscall_64.tbl, syscall_32.tbl, syscall_arm.tbl, syscall_generic.tbl):

Callx64i386g64arm32Since
sendfile40187711872.2
sendfile64-239-2392.6

sendfile64 (2.6) is the large-offset twin for 32-bit ABIs: the same transfer with a wider type for the offset argument; there is no separate slot on 64-bit arches.

Purpose

sendfile() copies data between two descriptors inside the kernel, avoiding the read-then-write round trip through user space. in_fd must be a descriptor whose file supports mmap(2)-like operations – in practice a regular file or block device, never a socket – and out_fd is the destination. The offset argument selects the semantics: NULL reads from in_fd’s file offset and updates it; non-NULL reads from *offset and on return stores the offset past the last byte read, leaving in_fd’s file offset untouched. Before 2.6.33 out_fd had to be a socket; since 2.6.33 it can be any file, and for a regular-file out_fd the file offset is adjusted. sendfile() transfers at most 0x7ffff000 (2,147,479,552) bytes per call, on 32-bit and 64-bit alike, and may write fewer bytes than requested – the caller retries for the rest. It was designed for serving files over TCP: pair it with TCP_CORK to avoid small packets around the payload (man2/sendfile.2 NOTES).

Synopsis

#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

Arguments and behavior

ArgumentBehavior
out_fdDestination descriptor, open for writing; socket-only before 2.6.33, any file since; O_APPEND on out_fd is not supported (EINVAL).
in_fdSource descriptor, open for reading; must support mmap(2)-like operations (no sockets); EINVAL if it does not.
offsetNULL: use and update in_fd’s file offset. Non-NULL: *offset is the start offset; on return it holds the offset after the last byte read; in_fd’s file offset is unchanged. Non-NULL with a nonseekable in_fd is ESPIPE.
countNumber of bytes to copy; capped at 0x7ffff000.

Return value and errors

Success returns the number of bytes written to out_fd (possibly fewer than requested; retry with the remainder). On error, -1 and errno: EAGAIN (O_NONBLOCK and the write would block), EBADF (in_fd not open for reading or out_fd not open for writing), EFAULT (bad address), EINVAL (descriptor not valid or locked; mmap-like operation unavailable for in_fd; count negative; O_APPEND on out_fd), EIO (unspecified error while reading in_fd), ENOMEM (insufficient memory reading in_fd), EOVERFLOW (count too large – would exceed the maximum size of the input or output file), ESPIPE (offset non-NULL but in_fd not seekable).

Flags and constants

None: sendfile() takes no flags argument. Per-I/O behavior flags do not exist here; the richer generalization is splice() (splice.md) with its SPLICE_F_* mask, and copy_file_range() for file-to-file copies (see the domain hub).

Security and notes

  • Zero-copy caveat: if out_fd is a socket or pipe with zero-copy support, the transferred portions of in_fd’s file must remain unmodified until the reader consumes them (man2/sendfile.2 NOTES) – do not truncate or rewrite the source mid-transfer.
  • History quirk: in Linux 2.4 and earlier out_fd could be a regular file, the 2.6.x series removed that, and 2.6.33 restored it (man2/sendfile.2 NOTES).
  • Fallback advice: applications should fall back to read()/write() when sendfile() fails with EINVAL or ENOSYS (filesystem without support, or pre-2.2 kernel).
  • The 0x7ffff000 cap and the partial-write retry pattern are shared with read()/write()/readv()/writev() (read.md, write.md, readv.md).
  • sendfile() changes neither file’s offset when offset is non-NULL, which is what makes loops over file chunks safe.

References