Part 4 · 1 chapters · ~8 min
Files and Descriptors
open, read, write and close, descriptor tables and open file descriptions, offsets and O_APPEND, dup and dup2 for redirection, pipes, buffering and fsync for durability, file permissions, descriptor limits and leaks, and memory-mapped files.
5
Reading, writing, durability
code
int fd = open("ledger.log", O_WRONLY | O_CREAT | O_APPEND, 0644); // O_APPEND: every write goes to the end atomically
if (fd < 0) { perror("open"); exit(1); }
write_all(fd, line, len);
if (fsync(fd) < 0) perror("fsync"); // write() reaching the page cache is not durable; fsync is (Storage course)
close(fd); // leaking descriptors ends in EMFILE: "too many open files"
// redirection, as a shell does it: cmd > out.txt 2>&1
int out = open("out.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
dup2(out, 1); dup2(out, 2); close(out);
// memory-mapped file: the file appears as memory; the page cache backs it
void *p = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);Durability on macOS: fsync there does not force the drive to flush its own cache; databases use fcntl(fd, F_FULLFSYNC) on macOS for true durability. On Linux, fsync of a new file also needs an fsync of its directory to make the name durable.
FILE DESCRIPTORS
small integers that name kernel objects
swipe the figure sideways, or tap expand for full screen
1/4
a number
open, socket and pipe return the lowest free integer in the process's descriptor table. 0, 1 and 2 are standard input, output and error.
an index into a table0, 1, 2 are standard