文件读写与缓存机制

文件读写与缓存机制

写文件:

1:stdio函数库

fopen/fwrite/fflush/fclose   File* fp

2: POSIX系统级别函数

open/write/close  fd

3:Windows系统级别函数

CreateFile/WriteFile/CloseHandle

**同步数据到磁盘:**FlushFileBuffers、fsync

使用stdio函数库操作文件,标准库会在用户空间中维护一个缓冲区(缓存)。这种缓冲机制是为了提高性能,减少系统调用的次数,因为系统调用有一定的开销。

缓冲机制的工作原理

写操作:

当使用 fwrite()fprintf() 等函数向文件写入数据时,数据首先被写入到标准库在用户空间中分配的缓冲区中。缓冲区满了之后,标准库会自动将缓冲区中的内容刷新到内核缓冲区上,并清空用户空间的缓冲区。也可以手动调用 fflush() 函数或 fclose() 函数来立即刷新缓冲区。

在这里插入图片描述

读操作:

当使用 fread()fgets() 等函数从文件读取数据时,数据会被读入到用户空间的缓冲区中。之后的读操作会从缓冲区中读取数据,直到缓冲区中的数据被读完,才会再次从内核缓冲区读取新的数据块到缓冲区中。

C标准库提供了三种类型的缓冲

全缓冲(full buffering):

对于那些能够定位(如磁盘文件)的文件,默认情况下使用全缓冲。缓冲区的大小通常较大,只有在缓冲区满时才刷新到内核缓冲区。

行缓冲(line buffering):

对于标准输入/输出(如stdin、stdout),默认使用行缓冲
当遇到换行符时,缓冲区中的内容会被刷新到内核缓冲区。

无缓冲(no buffering):

对于标准错误输出(如stderr),默认情况下不使用缓冲。
每次写入操作都会直接写入到磁盘。

实际写入磁盘

当数据被复制到内核缓冲区后,内核会根据其自身的调度策略决定何时真正将数据写入物理磁盘。内核通常会合并多个写入操作,以提高效率。此外,内核还可能延迟写入操作,直到有足够多的数据需要写入,或者直到某个特定的时间间隔过去。

强制写入磁盘

如果希望确保数据立即写入到物理磁盘上,而不是仅仅写入到内核缓冲区,需要使用特定的函数来同步内核缓冲区。在Windows中,可以使用 FlushFileBuffers() 函数来强制将内核缓冲区中的数据写入磁盘。在POSIX系统中,可以使用 fsync()fdatasync() 函数来达到同样的目的。


#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

int main() {
    int fd;
    const char *filename = "testfile.txt";
    const char *data = "Hello, POSIX!";
    ssize_t bytes_written;

    // 打开文件以写入模式
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    if (fd == -1) 
    {
        perror("Failed to open file");
        return 1;
    }

    // 写入数据
    bytes_written = write(fd, data, strlen(data));
    if (bytes_written != (ssize_t)strlen(data)) 
    {
        perror("Failed to write to file");
        close(fd);
        return 1;
    }

    // 强制将数据写入磁盘
    if (fsync(fd) == -1) 
    {
        perror("Failed to fsync");
        close(fd);
        return 1;
    }

    // 关闭文件
    if (close(fd) == -1) 
    {
        perror("Failed to close file");
        return 1;
    }

    return 0;
}

文件写入磁盘完整流程:

第一步: 数据首先写入到用户空间缓冲区。

第二步: 当缓冲区满或显式调用刷新函数时,数据被复制到内核缓冲区。

第三步: 要确保数据实际写入到物理磁盘,需要使用 fsync()(POSIX)或 FlushFileBuffers()(Windows)来同步内核缓冲区。

面试题

写文件时进程宕机,数据是否会丢失?

答案:

  • 使用stdio函数库,在进程宕机的时候,如果没有调用 fflush 或者 fclose 函数,那么数据丢失,如果调用了,就要看机器是否掉电,如果机器没掉电,那么数据不会丢失,如果机器掉电了,那么数据有可能丢失。

  • 使用系统级别函数库,在调用write函数后进程宕机,如果机器没掉电,因为数据已经到了内核缓冲区,此时数据不会丢失;如果机器掉电,那么数据有可能丢失。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

螺蛳粉只吃炸蛋的走风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值