From 68f667156f7913f3300019d20121b94507cff0db Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Fri, 27 Jun 2025 17:08:30 +0200 Subject: [PATCH] Chapter 4 --- chp4/README.md | 69 +++++++++++++++++++++++---------------------- chp4/buccaneer.txt | Bin 0 -> 148 bytes chp4/readv.c | 41 +++++++++++++++++++++++++++ chp4/writev.c | 45 +++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 33 deletions(-) create mode 100755 chp4/buccaneer.txt create mode 100644 chp4/readv.c create mode 100644 chp4/writev.c diff --git a/chp4/README.md b/chp4/README.md index 6f1aa4b..ef58438 100755 --- a/chp4/README.md +++ b/chp4/README.md @@ -1,42 +1,45 @@ # Chapter 4 – Advanced File I/O -## File Metadata and the `stat` Family -- Use `stat()`, `fstat()`, `lstat()` to retrieve file metadata: - - File type, size, inode number, permissions, ownership, timestamps (atime, mtime, ctime). -- The `stat` structure includes all these details. +## Scatter/Gather I/O +- Scatter/gather I/O allows reading or writing data to/from multiple buffers in a single system call. +- Uses `readv()` and `writev()`: + - `readv(fd, iov, iovcnt)`: reads into multiple buffers (`iov` array). + - `writev(fd, iov, iovcnt)`: writes from multiple buffers. +- Improves efficiency by reducing system calls. -## File Types -- Regular file, directory, symbolic link, character/block device, FIFO, socket. -- Use macros like `S_ISREG()`, `S_ISDIR()` to test file types. +## Event Poll (`select()`, `poll()`, `epoll`) +- Traditional multiplexing: `select()`, `poll()` (limited scalability). +- Linux-specific: `epoll` for efficient event notification. + - `epoll_create()`: create epoll instance. + - `epoll_ctl()`: control interest list (add, modify, remove fds). + - `epoll_wait()`: wait for events. +- Edge-triggered vs level-triggered modes. -## File Permissions and Modes -- Represented by 12 bits (e.g., `rwxr-xr--`), plus sticky/SUID/SGID bits. -- Manipulate with `chmod()`, `fchmod()`, `umask()`. -- Ownership changed with `chown()` and `fchown()`. +## Memory-Mapped Files (`mmap()`) +- Maps files or devices into memory for direct access. +- System calls: `mmap()`, `munmap()`. +- Benefits: faster I/O, shared memory. +- Use `msync()` to synchronize changes. +- Resizing mappings, changing protections. +- Advisory calls: + - `posix_fadvise()`: give advice about expected I/O patterns. + - `readahead()`: prefetch file data. +- Pros and cons of memory mapping. -## Links -- **Hard links**: multiple filenames point to the same inode. -- **Symbolic links**: separate files that reference other paths; can be broken. -- Use `link()`, `unlink()`, `symlink()`, `readlink()`. +## Asynchronous I/O and I/O Scheduling +- Distinction between synchronous and asynchronous I/O. +- Linux AIO APIs for asynchronous operations. +- I/O schedulers: + - Manage disk request ordering. + - Examples: CFQ, noop, deadline. +- Optimizing I/O performance by choosing schedulers. +- Concepts of disk addressing and request life cycle. -## Directories -- Open with `opendir()`, read entries with `readdir()`. -- Low-level: `getdents()` system call. +## Miscellaneous +- `ioctl()`: device-specific operations. +- Zero-copy transfers: `sendfile()`, `splice()`. -## File Timestamps -- `utime()`, `utimes()`, `futimens()`, and `utimensat()` to update access/modification times. +--- -## File Descriptors and Flags -- Manipulate with `fcntl()`: - - Set non-blocking mode (`O_NONBLOCK`), FD_CLOEXEC flag, file locks. - - Duplicate with `dup()` and `dup2()`. +> This chapter covers advanced Linux I/O techniques aimed at improving performance and flexibility in system programming. -## File Locking -- `flock()` for advisory locking (whole file). -- `fcntl()` for POSIX record locking (ranges). - -## Temporary Files -- `tmpfile()`, `mkstemp()` are safe methods to create temp files. - -## Summary -- Chapter 3 focuses on extended file handling: metadata, links, directories, file modes, and advanced descriptor manipulation. diff --git a/chp4/buccaneer.txt b/chp4/buccaneer.txt new file mode 100755 index 0000000000000000000000000000000000000000..4a84fb5735ad59f2f8339f4bc51d5e5b3e6c106e GIT binary patch literal 148 zcmX|)K?*`K3-_e8Es{jq6t8az;w~_6CbuUM?22ucB1U!;R}Spm z6_NDgy<+p3^mII&e<#|2B=btkttc@ED|TN2e>HnR$w=k$FQ>DLcaFf-YRfma%q0ol ItxGV4FCGUn_5c6? literal 0 HcmV?d00001 diff --git a/chp4/readv.c b/chp4/readv.c new file mode 100644 index 0000000..7f9e195 --- /dev/null +++ b/chp4/readv.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include + +int main(void) { + char foo[48], bar[51], baz[49]; + int fd = open("buccaneer.txt", O_RDONLY); + if (fd == -1) { + perror("open"); + return 1; + } + + // setup our iovec structures + struct iovec iov[3]; + iov[0].iov_base = foo; + iov[0].iov_len = sizeof(foo); + iov[1].iov_base = bar; + iov[1].iov_len = sizeof(bar); + iov[2].iov_base = baz; + iov[2].iov_len = sizeof(baz); + + // read into the structures with a single call + int nr = readv(fd, iov, 3); + if (nr == -1) { + perror("readv"); + return 1; + } + + for (int i = 0; i < 3; i++) + printf("%d: %s", i, (char *)iov[i].iov_base); + + if (close(fd)) { + perror("close"); + return 1; + } + + return 0; +} diff --git a/chp4/writev.c b/chp4/writev.c new file mode 100644 index 0000000..414364c --- /dev/null +++ b/chp4/writev.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(void) { + struct iovec iov[3]; + + char *buf[] = { + "The term buccaneer comes from the word boucan.\n", + "A boucan is a wooden frame used for cooking meet.\n", + "Buccaneer is the West Indies name for a pirate.\n" + }; + + int fd = open("buccaneer.txt", O_WRONLY | O_CREAT | O_TRUNC); + if (fd == -1) { + perror("open"); + return 1; + } + + // fill out three iovec structures + for (int i = 0; i < 3; i++) { + iov[i].iov_base = buf[i]; + iov[i].iov_len = strlen(buf[i]) + 1; + } + + // with a single call, write them all out + ssize_t nr = writev(fd, iov, 3); + if (nr == -1) { + perror("writev"); + return 1; + } + + printf("wrote %lu bytes\n", nr); + + if (close(fd)) { + perror("close"); + return 1; + } + + return 0; +}