C++笔记-文件IO-<fcntl.h>

<fcntl.h> 文件控制

一、是什么

<fcntl.h> = file control,提供 C 风格的文件系统调用:

内容 用途
open() 打开 / 创建文件
O_* 标志 控制打开方式
fcntl() 修改 fd 属性

二、open 原型

cpp 复制代码
int open(const char *pathname, int flags, mode_t mode);
参数 含义
pathname 文件路径
flags 打开方式(O_RDONLY、O_CREAT 等)
mode 权限,只在 O_CREAT 时用,如 0644
返回 成功 fd >= 0,失败 -1

三、常用标志

标志 含义
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写
O_CREAT 不存在就创建
O_APPEND 追加写,每次写到末尾
O_TRUNC 打开时清空
O_EXCL 配合 O_CREAT,文件已存在则失败
O_NONBLOCK 非阻塞

多个标志用 | 组合:

cpp 复制代码
open("data.log", O_CREAT | O_WRONLY | O_APPEND, 0644);

四、权限 0644

三位八进制:

复制代码
6 4 4
│ │ └─ 其他人:r--
│ └─── 组:r--
└───── 拥有者:rw-
数字 权限
4 读
2 写
1 执行
6 读+写
7 读+写+执行

五、读 / 写 / 关闭

需要 #include <unistd.h>

unistd=Unix Standard

cpp 复制代码
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int close(int fd);
返回值 含义
read > 0 实际读到的字节数
read = 0 文件读完 / 对端关闭
read = -1 出错
write > 0 实际写入的字节数
write = -1 出错

注意:write 可能写不全,大消息要循环写:

cpp 复制代码
size_t total = 0;
while (total < len) {
    ssize_t n = write(fd, buf + total, len - total);
    if (n <= 0) break;
    total += n;
}

六、落盘 fsync

需要 #include <unistd.h>

cpp 复制代码
fsync(fd);
  • 强制把内核缓冲区写到磁盘
  • 防崩溃丢数据
  • 比普通 write 慢很多

WAL (预写日志)必须用:

cpp 复制代码
write(fd, log.c_str(), log.size());
fsync(fd);              // 确保真落盘

七、定位 lseek

cpp 复制代码
off_t lseek(int fd, off_t offset, int whence);
whence 含义
SEEK_SET 从开头
SEEK_CUR 从当前位置
SEEK_END 从末尾
cpp 复制代码
lseek(fd, 0, SEEK_SET);   // 回到开头

八、最常用模板

追加写 + 落盘

cpp 复制代码
int fd = open("data.log", O_CREAT | O_WRONLY | O_APPEND, 0644);
if (fd < 0) { /* 出错 */ }

std::string log = "SET key value\n";
write(fd, log.c_str(), log.size());
fsync(fd);
close(fd);

只读打开

cpp 复制代码
int fd = open("data.txt", O_RDONLY);
char buf[1024];
ssize_t n;
while ((n = read(fd, buf, sizeof(buf))) > 0) {
    // 处理 buf 前 n 字节
}
close(fd);

九、常见坑

坑 说明
open 返回 -1 要检查 不检查后面全崩
write 可能写不全 大消息要循环
fsync 很慢 别每条都调,重要才调
O_APPEND 保证原子追加 多线程写同一 fd 安全
fd 用完要 close 否则泄漏
read 返回 0 是正常结束,不是错误

十、和 <fstream> 对比

<fcntl.h>(C 风格) <fstream>(C++ 风格)
类型 int fd ifstream / ofstream
打开 open("a.txt", O_RDONLY) ifstream in("a.txt")
读 read(fd, buf, n) getline(in, line) / in >> x
写 write(fd, buf, n) out << "hi"
关闭 close(fd) 自动 / in.close()
落盘 fsync(fd) ❌
非阻塞 fcntl ❌
网络 fd ✅ 同一套 ❌
逐行读 ❌ 自己处理 ✅ getline
格式化输出 ❌ ✅ <<
跨平台 Linux / POSIX ✅ 全平台
底层 系统调用 封装系统调用

十一、怎么选

场景 用哪个
读文本、逐行处理 ifstream + getline
写文本 ofstream
要 fsync 落盘 open + write + fsync
网络 socket read / write
要非阻塞 fcntl
跨平台 fstream

十二、总结

<fcntl.h> 是 C 风格底层文件 IO:open 打开,read/write 读写,fsync 落盘,close 关闭。

要落盘、要网络 fd、要非阻塞 → 用它;日常读文本 → 用 <fstream>。

相关推荐
别动我齐刘海7 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
程序员老陆7 小时前
C++ std::promise深度解析
c++·程序设计
青少儿编程课堂7 小时前
迪杰斯特拉(Dijkstra)算法:单源最短路与赛场路线规划
c++·python·算法·bfs·信息学竞赛
沫璃染墨9 小时前
《Qt从零入门系列(十三):QSS样式表详解——从选择器与层叠规则到控件美化实战》
开发语言·css·c++·qt·ui·qt6.3·qss
道尔柯南10 小时前
C++ 面向对象编程入门:类和对象(上)
开发语言·c++·算法
aqiu11111111 小时前
【C++算法打怪专栏】C++ `unordered_set` 常用初始化与插入方法总结
开发语言·c++·算法
Terra.K12 小时前
高精度阶乘求和模板深度解析
开发语言·c++·算法
智码看视界12 小时前
C++智能指针全景剖析及面试20问
开发语言·c++·深度学习·面试·内存管理·智能指针
Peregrine912 小时前
C++ - > 类和对象
java·c++·算法
‎ദ്ദിᵔ.˛.ᵔ₎14 小时前
c++11:fuction包装器
开发语言·c++