前言很多初学者学文件读写时会混淆三套东西Linux 原生系统调用open / read / write / closeC 语言标准库fopen / fread / fwrite / FILE*C 面向对象文件流ifstream / ofstream 文件对象最核心、最颠覆认知的一句话操作系统内核层面根本没有“文件对象”、“文件结构体”。内核只认一个东西整型文件描述符 fd。所有 C / C 的文件类型全部都是上层语言库封装底层最终全部回归 fd。一、最底层Linux 内核层面 —— 只有 fd没有对象1.1 内核真正的文件操作方式Linux 内核不认识字符串文件名、不认识结构体、不认识类、不认识对象。内核只认识int 类型的文件描述符 fd所有系统调用原生接口int open(文件名, 打开方式); ssize_t read(fd, 缓冲区, 大小); ssize_t write(fd, 缓冲区, 大小); int close(fd);.2 核心逻辑重中之重文件名只给 open 使用用来在磁盘找到文件、打开文件、占用资源一旦打开成功后续读写彻底抛弃文件名后续所有 read / write 只靠 fd 整数令牌 操作文件所以绝对不能写错误read(test.txt, buf, 1024);正确必须写先 open 拿 fd再 read(fd)1.3 为什么 0、1、2 不用 open进程启动时bash 默认帮我们提前打开三个标准文件流fd 0标准输入键盘 stdinfd 1标准输出屏幕 stdoutfd 2标准错误屏幕 stderr这也是为什么我们可以直接写read(0, buf, sizeof(buf)); // 直接读键盘 write(1, buf, strlen(buf)); // 直接写屏幕二、C 语言层没有对象只有库封装的 FILE* 结构体2.1 C 语言原生特点C 语言没有类、没有对象、没有面向对象。所以 C 语言不可能有“文件对象”。C 语言的文件操作FILE*只是标准库封装的一个结构体。2.2 FILE* 底层本质FILE 结构体内部藏着底层真实 fd文件描述符用户层缓冲区C库缓存读写状态、偏移、标志位也就是说fopen 封装了 openfread 封装了 readfclose 封装了 close2.3 层级关系内核 fd真实底层 ← 被 C库包装 → FILE*上层结构体三、C 层真正有「文件对象」3.1 C 引入面向对象 IO 流C 对文件操作做了彻底面向对象封装ifstream文件读对象ofstream文件写对象fstream文件读写对象代码风格变成ifstream ifs(test.txt); ifs.read(buf, 1024);这里的ifs 是实打实的对象有成员变量、成员函数、构造析构。3.2 重点C 对象依然不是内核机制很多人误解以为 C 的文件对象是操作系统提供的。实则是错误的C 的 ifstream / ofstream 只是C 标准库上层封装。Linux 底层依然打开文件靠 open、读写靠 read/write、内核只认 fdC 对象内部依然藏着一个底层 fd。四、终极三层层级图1. 操作系统内核最底层只有 int fd 文件描述符 系统调用无对象、无结构体、无缓存机制、最原始2. C 语言标准库中间层封装出 FILE* 结构体增加用户缓冲区、封装系统调用、更好用3. C 标准库最高层封装出 ifstream / ofstream 流对象面向对象、重载运算符、更优雅、更安全五、总结Linux 内核没有文件对象只有 fd 文件描述符所有文件IO本质都是操作 fdC 语言没有对象FILE* 只是库提供的结构体包装C 才有真正的文件对象流对象属于语言库封装不改变内核机制文件名只用于 open 阶段读写阶段一律只用 fd高层库C stdio / C fstream全部是对底层 read/write 的封装六、一句话彻底通透操作系统是最朴实的只认数字 fdC 语言帮你包装成结构体C 帮你升级成面向对象。但底层内核从来没变过。