“标准 I/O 用 fopen,底层控制用 open; 要 mmap 必 open,跨平台选 fopen。”

📌 一句话总结

open() / read() / write() / close() fopen() / fread() / fwrite() / fclose()
所属层级 系统调用(System Call) ------ 内核接口 标准 C 库函数(Standard I/O) ------ 用户库封装
头文件 <fcntl.h>, <unistd.h> <stdio.h>
返回类型 int(文件描述符,file descriptor) FILE*(文件流指针)
缓冲机制 无缓冲(每次调用都陷入内核) 带缓冲(减少系统调用次数,提高效率)
可移植性 类 Unix 系统(Linux/macOS/WSL),非 ANSI C ANSI C 标准,跨平台(Windows/Linux/macOS)
适用场景 高性能、底层控制、设备文件、mmap 一般文件读写、文本处理、快速开发

🔍 详细对比

1. 层级与实现

  • open() 系列

    • 操作系统提供的系统调用,直接与内核交互。
    • 每次 read()/write() 都会触发一次 系统调用(syscall) ,开销较大。
  • fopen() 系列

    • C 标准库(如 glibc)对系统调用的封装
    • 内部使用缓冲区(通常 4KB~8KB),只有缓冲区满或显式刷新(fflush)时才调用 write()

✅ 举例:

fwrite() 写 1000 次 1 字节 → 可能只触发 1 次 write() 系统调用。

write() 写 1000 次 1 字节 → 触发 1000 次 系统调用(慢!)。


2. 缓冲机制(关键区别!)

函数系列 缓冲类型 行为
fopen 全缓冲(文件) / 行缓冲(终端) 数据先存入 FILE* 的内部缓冲区
open 无缓冲 数据直接传给内核
scss 复制代码
// 标准 I/O:可能看不到立即输出
FILE *fp = fopen("log.txt", "w");
fprintf(fp, "Hello");  // 数据在缓冲区,未写入磁盘!
// 需要 fclose(fp) 或 fflush(fp) 才真正写入

// 系统调用:立即写入
int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);
write(fd, "Hello", 5);  // 立即进入内核,写入磁盘(或 page cache)

3. 返回值与错误处理

返回值 错误检查方式
open fd(≥0 成功,-1 失败) 检查返回值是否为 -1,用 errnoperror()
fopen FILE*(非 NULL 成功,NULL 失败) 检查是否为 NULL,用 perror()

4. 功能与灵活性

能力 open() 系列 fopen() 系列
打开设备文件(如 /dev/tty ✅ 支持 ⚠️ 可能支持,但不推荐
非阻塞 I/O、异步 I/O ✅ 支持(配合 O_NONBLOCK 等) ❌ 不支持
mmap() 配合使用 ✅ 必须用 open()mmap 需要 fd ❌ 不能直接用(需 fileno() 转换,不推荐)
文本模式自动换行转换(Windows) ❌ 无 "r"/"w" 模式自动处理 \n\r\n
格式化输入输出(printf/scanf ❌ 无 ✅ 支持 fprintf, fscanf

5. 性能对比(典型场景)

场景 推荐使用
读写大文件(如 1GB 视频) 两者均可,open + 大块 read 更可控
频繁小量写入(如日志) fopen(缓冲减少 syscall)
需要 mmapfcntlioctl ✅ 必须用 open
跨平台程序(Windows + Linux) fopen(标准 C)
实时性要求高、避免缓冲延迟 open(或 setvbuf 关闭缓冲)

🔄 如何互相转换?

虽然不推荐混用,但技术上可行:

ini 复制代码
#include <stdio.h>
#include <unistd.h>

FILE *fp = fopen("test.txt", "w");
int fd = fileno(fp);        // FILE* → fd

int fd2 = open("test2.txt", O_WRONLY | O_CREAT, 0666);
FILE *fp2 = fdopen(fd2, "w"); // fd → FILE*

⚠️ 注意:混用可能导致缓冲不一致(如先 write(fd)fwrite(fp)),强烈建议不要混用同一个文件


✅ 总结:如何选择?

你想要...... 用哪个?
快速读写文本文件、做作业、写小程序 fopen 系列(简单、安全、标准)
使用 mmap()、控制文件锁、操作设备 open 系列(底层、灵活)
最高性能(自己管理缓冲) open + 大块 read/write
跨平台兼容性 fopen
确保数据立即写入磁盘 open + fsync(),或 fopen + fflush() + fsync(fileno(fp))

💡 记住这个口诀:

"标准 I/O 用 fopen,底层控制用 open
mmapopen,跨平台选 fopen。"

相关推荐
深思慎考2 小时前
LinuxC++项目开发日志——基于正倒排索引的boost搜索引擎(5——通过cpp-httplib库建立网页模块)
linux·c++·搜索引擎
李小枫3 小时前
在linux上安装kafka,并使用kafka-clients实现消费者
linux·kafka·linq
煤球王子3 小时前
浅学内存分配与释放(二)
linux
dessler3 小时前
Hadoop HDFS-认证(Kerberos) 部署与配置
linux·运维·hdfs
360智汇云4 小时前
k8s共享存储fuse-client三种运行方案对比
java·linux·开发语言
Mr.45675 小时前
Linux&Windows环境下Nacos3.1.0详细安装配置指南:从零到生产就绪
linux·运维·服务器
峰顶听歌的鲸鱼6 小时前
30.Linux DHCP 服务器
linux·运维·服务器·笔记·学习方法
Lzc7746 小时前
Linux的网络基础
linux·linux的网络基础