Linux系统编程(1)文件
-
Linux系统编程(1)文件操作的层次结构
我将在此持续更新Linux系统编程的教学,有不妥,不正确的地方望看到的人指正
首先对于IO的操作,或者各种IO函数,他应当可以被分为下述的几个部分,我将采用总分的结构,在系统描述每一个部分之前,先对整个linux IO有一个大致的认识
第 0 层:用户态缓冲 I/O(不是系统调用,但最“上层”)
特点:你操作的是
FILE*,数据先进入 用户态缓冲区,再由 libc 在合适时机调用write/read等进入内核。
典型 API:fopen/fclose/fread/fwrite/fgets/fputs/fgetc/fputc/printf/scanf,setvbuf/fflush/ferror/feof
要点:这层决定“行缓冲/全缓冲/无缓冲”,以及很多“看起来一次写入”,底下可能拆成多次系统调用。第 1 层:文件描述符(fd)上的“无缓冲”I/O 系统调用(VFS 入口)
特点:你提供用户缓冲区地址,内核负责把数据在 用户内存
内核 间拷贝,并通过 VFS/页缓存/文件系统把它落到磁盘或读出来。1.1 基础数据读写
-
open/openat/creat,close -
read,write -
lseek(改变文件偏移)
1.2 更“语义化/性能化”的读写
-
定位读写(不改文件偏移):
pread,pwrite -
向量 I/O(scatter/gather):
readv,writev -
按大小截断:
truncate,ftruncate
这一层是“系统编程”的主干:大多数 I/O 都能归结为这些 fd syscalls 的组合。
第 2 层:内核缓冲/页缓存语义相关(同样还是 fd 接口,但语义更“接近内核缓存”)
特点:你不只是“读写字节”,还在控制“什么时候算写成功、什么时候必须落盘、缓存如何使用”。
2.1 同步与持久化
fsync,fdatasync,sync,syncfs
解决“写进页缓存了但还没真正落盘”的一致性/崩溃恢复问题。
2.2 访问模式与预取/淘汰建议(属于“提示/策略”)
-
posix_fadvise(libc 封装,底层可能用fcntl/内核建议路径) -
readahead(Linux 专有,提示预读)
这类接口不一定“立刻改变数据”,但会影响页缓存、预读、回写策略,从而影响性能与时延。
第 3 层:绕开“显式 read/write”的 I/O 路径
3.1 内存映射 I/O(mmap 路径)
特点:文件数据映射到进程虚拟内存,通过缺页异常把页拉进来;写回由回写机制处理。
mmap,munmap,msync(以及mprotect/mlock等相关)
直觉:
read/write是“你显式搬运”,mmap是“让内核分页系统替你搬运”。3.2 零拷贝/内核内搬运(减少 user<->kernel 拷贝)
-
sendfile(文件→socket 常用) -
splice,tee,vmsplice(在 fd 之间搬运/管道相关)
第 4 层:I/O 多路复用与事件驱动(“等 I/O”也是 I/O 的一部分)
特点:面向大量 fd 时,不是忙等,而是让内核告诉你“哪个 fd 可读/可写/出错”。
-
select,pselect -
poll,ppoll -
epoll_create/epoll_ctl/epoll_wait
(扩展:
inotify用于文件系统事件通知,也常被归到“事件 I/O”这一层。)第 5 层:异步 I/O(发起后不阻塞当前线程)
特点:读写请求提交给内核,之后再取完成事件;适合高并发、减少线程阻塞。
-
POSIX AIO:
aio_read/aio_write/aio_error/aio_return(多为库接口,底层实现依系统而异) -
Linux AIO:
io_setup/io_submit/io_getevents(更“Linux 内核味”)
更现代的
io_uring也属于这一类(但它比 Love 那本书年代新很多,书里大概率没有重点展开)。第 6 层:控制类系统调用(不直接搬运数据,但决定“怎么 I/O”)
6.1 文件描述符控制与状态
-
fcntl:设置/获取 fd 标志(如O_NONBLOCK)、记录锁(F_SETLK等)、复制 fd 等 -
dup/dup2/dup3
6.2 设备/驱动专用控制面(“像 I/O,但本质是控制”)
ioctl:字符设备/块设备/终端/网络设备等大量控制都走它
第 7 层:命名空间与元数据 I/O(“文件系统操作”,不等于数据读写)
特点:改的是目录项、inode 元数据、权限、链接关系;不直接等价于读写文件内容。
-
元数据查询:
stat/fstat/lstat -
权限属主:
chmod/fchmod,chown/fchown,umask,access -
链接与重命名:
link/unlink/symlink/readlink,rename -
目录与节点:
mkdir/rmdir,mknod -
目录读取:
getdents(系统调用层),上层常用opendir/readdir(库封装)
总体结构如下
┌───────────────────────────────────────────────────────────────────────────┐ │ USER SPACE │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ Level 0: User-mode Buffering (glibc FILE*) │ │ │ │ │ │ │ │ fopen / fread / fwrite / printf │ │ │ │ ┌──────────────────────────┐ ┌──────────────────────────────┐ │ │ │ │ │ User Buffer (glibc) │ │ Line / Full Buffering │ │ │ │ │ └──────────────────────────┘ └──────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ ├──────────────────── SYSTEM CALL INTERFACE / BOUNDARY ─────────────────────┤ │ │ │ KERNEL SPACE │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ Level 1: FD Standard Syscalls & VFS Entry │ │ │ │ │ │ │ │ open / read / write │ │ │ │ ┌───────────────────────┐ ┌───────────────────────────────┐ │ │ │ │ │ User → Kernel Copy │ │ VFS (file / inode / dentry) │ │ │ │ │ └───────────────────────┘ └───────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌───────────────────────┐ ┌──────────────────────────┐ ┌─────────┐ │ │ │ Level 3: Zero-copy │ │ Level 2: Page Cache │ │ Level 4 │ │ │ │ mmap / sendfile / │ │ fsync / fdatasync │ │ epoll │ │ │ │ splice │ │ readahead │ │ poll │ │ │ └───────────────────────┘ └──────────────────────────┘ └─────────┘ │ │ │ │ │ │ │ │ ▼ ▼ │ │ ┌──────────────────────────┐ ┌───────────────┐ │ │ │ Level 5: Async I/O │ │ Level 6: │ │ │ │ AIO / io_uring │ │ fcntl / ioctl │ │ │ └──────────────────────────┘ └───────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ Level 7: Metadata & Namespace Ops │ │ │ │ │ │ │ │ stat / chmod / rename │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ Block Device Drivers & I/O Scheduler │ │ │ │ (bio / request / elevator) │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ │ ↓ ↓ ↓ │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ HARDWARE STORAGE (Disk / SSD / NVMe) │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────────────────────────────────────┘用户操作缓冲IO结构
┌──────────────────────────────────────────────────────────────────────────────┐ │ USER SPACE │ │ │ │ ┌────────────────────────────────────────────────────────────────────────┐ │ │ │ Level 0: User-mode Buffering (glibc FILE*) │ │ │ │ │ │ │ │ Application calls: │ │ │ │ fopen(path, mode) │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ glibc fopen implementation │ │ │ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ │ │ │ FILE struct │ │ │ │ │ │ │ │ │ │ │ │ int fd ────────────────┐ │ │ │ │ │ │ User-mode Buffer │ char* base / ptr / size │ │ │ │ │ │ Flags (mode, buffering) │ line / full / none │ │ │ │ │ └──────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ └── returns FILE* fp │ │ │ │ │ │ │ │ Application I/O: │ │ │ │ │ │ │ │ fwrite(ptr, size, nmemb, fp) │ │ │ │ fread (ptr, size, nmemb, fp) │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ │ │ │ User-mode Buffer (glibc memory) │ │ │ │ │ │ │ │ │ │ │ │ [ data ][ data ][ data ][ .... ][ free space ] │ │ │ │ │ │ │ │ │ │ │ │ Data copied between application buffer and libc buffer │ │ │ │ │ └──────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ │ (buffer full / fflush) │ │ │ │ ▼ │ │ ├──────────────────────── SYSTEM CALL INTERFACE / BOUNDARY ────────────────────┤ │ │ │ KERNEL SPACE │ │ │ │ ┌───────────────────────────────┐ ┌───────────────────────────────┐ │ │ │ open(path, flags, mode) │ │ write(fd, buffer, count) │ │ │ │ System Call │ │ read (fd, buffer, count) │ │ │ └───────────────────────────────┘ └───────────────────────────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌────────────────────────────────────────────────────────────────────────┐ │ │ │ Kernel Page Cache (VFS) │ │ │ │ │ │ │ │ - file / inode / dentry │ │ │ │ - page cache │ │ │ │ - readahead / writeback │ │ │ └────────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────────────────────────────────────────────────────────────┐ │ │ │ Block Device Driver │ │ │ │ │ │ │ │ - bio / request │ │ │ │ - I/O scheduler │ │ │ └────────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────────────────────────────────────────────────────────────┐ │ │ │ HARDWARE STORAGE (Disk / SSD / NVMe) │ │ │ └────────────────────────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘其大致结构基本如下,后续,将对每一个模块进行详细系统的论述
-