read(2)
๐ธ read(2) โ or, "bestie, get me those bytes" ๐ธ
okay so this is the read(2) page from the Linux man-pages โ you know, the manual's abbr is read(2) and it lives in the System Calls Manual section. it's the libc party. let's get into it ๐
โจ NAME โจ
read โ read from a file descriptor
๐ LIBRARY ๐
Standard C library (libc, -lc) โ like, the normal one, no extra linking drama ๐
๐ SYNOPSIS ๐
#include <unistd.h>
ssize_t read(size_t count;
int fd, void buf[count], size_t count);
yes bestie that's literally how it's printed, don't come for me ๐
๐ฆ DESCRIPTION ๐ฆ
so read() tries to read up to count bytes out of the file descriptor fd, and dumps them into the buffer that starts at buf. that's the whole gig. iconic. โจ
on files that support seeking, the read kicks off at the file offset, and then the file offset gets bumped up by however many bytes were actually read. and if the file offset is sitting at or past the end of the file? then nothing gets read, and read() just returns zero. end of story, no bytes, bye ๐
if count is zero, read() may still spot the errors listed below. but if there are no errors โ or if read() doesn't even bother checking for errors โ then a read() with a count of 0 returns zero and does literally nothing else. zero effort, zero consequences, main character energy ๐
and per POSIX.1: if count is bigger than SSIZE_MAX, the result is implementation-defined ๐ญ โ for the upper limit on Linux, scroll down to NOTES, bestie.
๐ RETURN VALUE ๐
on success you get back the number of bytes read (and if that number is zero, that means end of file ๐ฅบ), and the file position gets advanced by that same number.
and listen โ it is NOT an error if that number is smaller than the number of bytes you asked for. totally normal, happens all the time, e.g. because fewer bytes are actually available right now (maybe you're close to end-of-file, maybe you're reading from a pipe, maybe it's a terminal), or because read() got interrupted by a signal. see also NOTES, bestie.
on error, -1 comes back and errno gets set to tell you what went wrong. in that case, whether the file position (if there even is one) changes is left unspecified โ so like, don't count on it. ๐
๐ ERRORS ๐
okay here's the whole roster, no skips:
EAGAINโ the fdfdpoints at a file that is not a socket and it's been marked nonblocking (O_NONBLOCK), and the read would block. for more on theO_NONBLOCKflag, go peepopen(2).EAGAINorEWOULDBLOCKโ the fdfdpoints at a socket and it's been marked nonblocking (O_NONBLOCK), and the read would block. POSIX.1-2001 says either of these errors is allowed here, and it does not require the two constants to have the same value โ so if you want your app to be portable, check for both possibilities, periodt.EBADFโfdis not a valid file descriptor, or it's not open for reading. sorry babe, no reading privileges ๐ซEFAULTโbufis outside your accessible address space. that memory is not yours, bestie, don't touch it.EINTRโ the call got interrupted by a signal before any data was read. seesignal(7)for the lore.EINVALโfdis attached to an object that's unsuitable for reading. OR: the file was opened with theO_DIRECTflag, and either the address given inbuf, the value given incount, or the file offset is not suitably aligned. (alignment girlies, you know who you are ๐ )EINVALโfdwas created by a call totimerfd_create(2)and you handedread()a buffer of the wrong size. seetimerfd_create(2)for more.EIOโ I/O error. this one shows up, for example, when the process is in a background process group, tries to read from its controlling terminal, and either it's ignoring or blockingSIGTTIN, or its process group is orphaned ๐ญ. it can also happen when there's a low-level I/O error while reading from a disk or a tape. and one more possible cause ofEIOon networked filesystems: an advisory lock had been taken out on the file descriptor and that lock got lost. see the Lost locks section offcntl(2)for the details.EISDIRโfdrefers to a directory. bestie, that's a folder, not a file ๐- Other errors may occur, depending on the object connected to
fdโ so like, surprises are possible. stay safe out there โจ
โญ STANDARDS โญ
POSIX.1-2008. certified. ๐
๐ง HISTORY ๐ง
SVr4, 4.3BSD, POSIX.1-2001. ancient lineage, still slaying ๐
๐ฅ NOTES ๐ฅ
on Linux, read() (and its similar system calls) will transfer at most 0x7ffff000 (2,147,479,552) bytes, and it returns the number of bytes it actually transferred. and yes, this holds on both 32-bit and 64-bit systems, no cap. ๐ซถ
on NFS filesystems, reading small amounts of data will update the timestamp only the first time โ subsequent calls might not do it. why? client side attribute caching, bestie: most (if not all) NFS clients leave st_atime (the last file access time) updates up to the server, and client-side reads that get satisfied out of the client's cache will not cause st_atime updates on the server, because there were no server-side reads at all. you can get UNIX semantics back by disabling client-side attribute caching, but in most situations that will substantially increase server load and decrease performance. so, like, pick your struggle ๐
๐ BUGS ๐
according to POSIX.1-2008/SUSv4 Section XSI 2.9.7 ("Thread Interactions with Regular File Operations"):
All of the following functions shall be atomic with respect to each other in the effects specified in POSIX.1-2008 when they operate on regular files or symbolic links: ...
among the APIs listed after that are read() and readv(2). and among the effects that should be atomic across threads (and processes) are updates of the file offset. however โ before Linux 3.14, this was not the case ๐ญ. if two processes sharing an open file description (see open(2)) performed a read() (or readv(2)) at the same time, then the I/O operations were not atomic when it came to updating the file offset, and the result was that the reads in the two processes might (incorrectly!) overlap in the blocks of data they got. this problem was fixed in Linux 3.14. so if you're on something older than thatโฆ thoughts and prayers ๐
๐ SEE ALSO ๐
close(2), fcntl(2), ioctl(2), lseek(2), open(2), pread(2), readdir(2), readlink(2), readv(2), select(2), write(2), fread(3)
and that's the whole page, bestie, no notes ๐ this was Linux man-pages 6.20, dated 2026-02-08, and yes the page itself is literally called read(2). go read some bytes. drink water. mwah ๐ซถโจ๐
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: Linux-man-pages-copyleft
- Copyright 2009-2015, Michael Kerrisk <mtk.manpages@gmail.com>
- Copyright 1992, Drew Eckhardt <drew@cs.colorado.edu>
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms