将数据写入文件的系统调用

数据同步与持久性保证

在学习和了解双缓冲时的思考中想到 C++ 中的 std::fstream 也有一个缓冲区, 并且它的 flush 操作与我自己额外实现的缓冲区有何关联?

自己创建的缓冲区是用于将数据累积, 然后一次性写入 std::fstream 的缓冲区, 之后再执行 flush 操作, 以确保数据的写入. 感觉有点多余

随着涉及到文件写入和持久性保证的知识点变多, 并将了解到的信息整理一下(仅限于Linux)

关于数据同步和持久性保证的重要系统调用. 有四个常用的系统调用, 它们分别是 fdatasync, fsync, syncfssync.

补充说明: 文件分为 元数据部分数据部分

元数据部分指的是文件的创建时间,修改时间, 权限等附加的信息

1. fdatasync

cpp 复制代码
int fdatasync(int fd);

将文件的 ++数据部分++ 同步到磁盘, 以确保数据的持久性. 通常用于需要高可靠性的场景, 如数据库日志.

c++ 复制代码
#include <iostream>
#include <fstream>
#include <unistd.h>

int main() {
    std::ofstream file("data.txt");
    if (!file.is_open()) {
        std::cerr << "Failed to open file." << std::endl;
        return 1;
    }

    // 写入数据到文件
    file << "Hello, World!" << std::endl;

    // 执行 fdatasync 将数据部分同步到磁盘
    int fd = file.rdbuf()->fd();
    if (fd != -1) {
        if (fdatasync(fd) == -1) {
            std::cerr << "Failed to fdatasync." << std::endl;
            return 1;
        }
    }

    file.close();
    std::cout << "Data is safely on disk." << std::endl;

    return 0;
}

2. fsync

cpp 复制代码
int fsync(int fd);

fdatasync 类似, 将文件的++数据部分++ 和++元数据部分++同步到磁盘, 提供更高的一致性.

性能开销较大, 因此在需要更高一致性的情况下使用.

c++ 复制代码
#include <iostream>
#include <fstream>
#include <unistd.h>

int main() {
    std::ofstream file("data.txt");
    if (!file.is_open()) {
        std::cerr << "Failed to open file." << std::endl;
        return 1;
    }

    // 写入数据到文件
    file << "Hello, World!" << std::endl;

    // 执行 fsync 将数据部分和元数据同步到磁盘
    int fd = file.rdbuf()->fd();
    if (fd != -1) {
        if (fsync(fd) == -1) {
            std::cerr << "Failed to fsync." << std::endl;
            return 1;
        }
    }

    file.close();
    std::cout << "Data and metadata are safely on disk." << std::endl;

    return 0;
}

3. syncfs

cpp 复制代码
int syncfs(int fd);

将指定文件系统的缓冲区数据同步到磁盘. 为特定文件系统的同步需求提供更为灵活的选择.

c++ 复制代码
#include <iostream>
#include <unistd.h>
#include <fcntl.h>

int main() {
    // 打开文件
    int fd = open("data.txt", O_RDWR | O_SYNC);
    if (fd == -1) {
        std::cerr << "Failed to open file." << std::endl;
        return 1;
    }

    // 写入数据到文件
    const char* data = "Hello, World!";
    write(fd, data, strlen(data));

    // 执行 syncfs 将文件系统的缓冲区数据同步到磁盘
    if (syncfs(fd) == -1) {
        std::cerr << "Failed to syncfs." << std::endl;
        return 1;
    }

    close(fd);
    std::cout << "Data is safely on disk." << std::endl;

    return 0;
}

4. sync

cpp 复制代码
void sync(void);

sync 将所有挂载的文件系统的缓冲区数据刷新到磁盘. 虽然提供较高的数据保障, 但开销较大需要谨慎使用.

c++ 复制代码
#include <iostream>
#include <unistd.h>

int main() {
    // 执行 sync 将所有挂载的文件系统的缓冲区数据刷新到磁盘
    sync();

    std::cout << "All mounted filesystems are synced to disk." << std::endl;

    return 0;
}

区别:flush 和 fdatasync

  • flush : flush 操作将数据从内存刷新到文件, 但不一定同步到磁盘. 可能会导致数据丢失, 在需要数据持久性的场景下应谨慎使用. (如果是自己写的垃圾日志就用这个, 没必要追求更高的可靠性)

  • fdatasync : 相对于 flush提供更高的数据安全性. 将文件的数据部分同步到磁盘降低了数据丢失的风险. 非常适合高可靠性的需求, 如数据库日志.

相关推荐
---学无止境---30 分钟前
Linux中基数树批量查询数据项相关函数的实现
linux
我也想失去烦恼2 小时前
Linux系统/etc/hosts文件中配置了主机解析,但还是无法解析ip
linux·运维·服务器
R-G-B3 小时前
【25】MFC入门到精通——MFC静态文本框 中字符串 连续输出 不覆盖先前的文本 换行输出
c++·mfc·mfc静态文本框输出字符串·mfc静态文本框连续输出字符串·mfc静态文本框换行输出字符串
deng-c-f4 小时前
Linux C/C++ 学习日记(29):IO密集型与CPU密集型、CPU的调度与线程切换
linux·学习·线程·cpu·io密集·cpu密集
FFZero16 小时前
【C++/Lua联合开发】 (二) Lua调用C++函数
c++·junit·lua
报错小能手6 小时前
linux学习笔记(43)网络编程——HTTPS (补充)
linux·网络·学习
报错小能手6 小时前
linux学习笔记(45)git详解
linux·笔记·学习
CoderCodingNo7 小时前
【GESP】C++四级真题 luogu-B4068 [GESP202412 四级] Recamán
开发语言·c++·算法
一个不知名程序员www7 小时前
算法学习入门---双指针(C++)
c++·算法
Maple_land7 小时前
常见Linux环境变量深度解析
linux·运维·服务器·c++·centos