fread,fwrite数据写磁盘流程|fflush--linux编程写文件注意问题(fwrite没有直接写入文件)

目录

fread,fwrite数据写入磁盘的流程

fwrite,fflush

fwrite和write的区别

fwrite,fflush-----linux编程写文件注意问题(fwrite没有直接写入文件)


fread,fwrite数据写入磁盘的流程

2019-11-07 09:28:08

fwrite,fflush

fwrite,fflush,你不知道的事!_zhangxiong2532的博客-CSDN博客_fwrite和fflush

fread,fwrite>> CLib buffer内存缓冲(用户空间) -->fflush>>page  cache内核缓冲--->fsync>>磁盘

fflush:标准I/O函数(如:fread,fwrite)会在内存建立缓冲,该函数刷新内存缓冲,将内容写入内核缓冲,要想将其写入磁盘,还需要调用fsync。(先调用fflush后调用fsync,否则不起作用)。

sync、fsync、fdatasync、fflush函数区别和使用举例_lhb0709的博客-CSDN博客_fsync

调用fwrite后,把数据从application buffer 拷贝到了 CLib buffer,即C库标准IObuffer。fwrite返回后,数据还在CLib buffer,如果这时候进程core掉。这些数据会丢失。没有写到磁盘介质上。当调用fclose的时候,fclose调用会把这些数据刷到高速缓冲块,如果不手动调用fsync,fclose之后掉电再查看数据可能没有刷到磁盘上。

除了fclose方法外,还有一个主动刷新操作fflush 函数,不过fflush函数只是把数据从CLib buffer 拷贝到page  cache 中,并没有刷新到磁盘上,从page cache刷新到磁盘上可以通过调用fsync函数完成。 

从上面类子看到,一个常用的fwrite函数过程,基本上历经千辛万苦,数据经过多次copy,才到达目的地。有人心生疑问,这样会提高性能吗,反而会降低性能吧。这个问题先放一放。

有人说,我不想通过fwrite+fflush这样组合,我想直接写到page cache。这就是我们常见的文件IO调用read/write函数。这些函数基本上是一个函数对应着一个系统调用,如sys_read/sys_write. 调用write函数,是直接通过系统调用把数据从应用层拷贝到内核层从application buffer 拷贝到 page cache 中

关于linux系统调用write()


调用一次write()完毕,是不是已经写到磁盘上了?
是不是调用一次write(),就是一次写请求,不管写多少个字符进去,调用完都已经通过缓冲区写到磁盘上了?
那么fsync()这个函数是不是指将缓冲区的写到磁盘上,如果是,write完再fsync是不是多此一举?
我想实现的是可以先创建一个文件,然后写一些东西到该文件的缓冲区,再调用fsync()写入磁盘,请问如何实现?

当你用write之后,内核就响应write系统调用sys_write,然后向高速磁盘缓冲块page  cache写入数据,之后,你如果用stat,或者read时,系统首先会在高速缓冲块中去查看相应的数据是否在块中,如果不是,然后再调用磁盘驱动加载磁盘数据到高速缓冲块中,然后再由高速缓冲块中返回你要的数据!!!!!这就是你用stat()输出st_size,就是写入的个数的原因!!!!!
系统会在合适的时机再向真正的硬件写入高速缓冲块中的数据,也可以用fsync强制把高速缓冲块中的相应数据写入磁盘!!!!!!!          

关于write()和fsync()__write_fsync_高速缓_缓冲区_关于__

https://blog.csdn.net/xiaofei0859/article/details/51145051

fwrite和write的区别

fwrite是ANSI C的写函数,带缓冲(应用层缓冲);write/read是POSIX 的写函数,不带缓冲(应用层缓冲)
请问:

1. 带不带缓冲是指什么意思??

fwrite-->clib buffer-->pagecache-->……

write-->pagecache-->……

 2. 既然write不带缓冲,为什么write(int fd, const void *buf, size_t count) 是把缓冲区的字节写入fd相关联的文件中,read(int fd, void *buf, size_t count),是将fd关联的文件读入到缓冲区buf中?? 

首先要明白不带缓冲的概念:

所谓不带缓冲,并不是指内核不提供缓冲,而是只单纯的系统调用,不是函数库的调用。系统内核对磁盘的读写都会提供一个块缓冲,当用write函数对其写数据时,直接调用系统调用,将数据写入到块缓冲进行排队,当块缓冲达到一定的量时,才会把数据写入磁盘。因此所谓的不带缓冲的I/O是指进程不提供缓冲功能。

每调用一次write或read函数,直接系统调用
而带缓冲的I/O是指进程对输入输出流进行了改进,提供了一个流缓冲,当用fwrite函数网磁盘写数据时,先把数据写入流缓冲区中,当达到一定条件,比如流缓冲区满了,或刷新流缓冲,这时候才会把数据一次送往内核提供的块缓冲,再经块缓冲写入磁盘 

fwrite是带缓冲的,write不带缓冲。

举例说明如下:
如果文件的大小是8k。
若用write,且只分配了2k的缓存,则要将此文件读入需要做4次系统调用。(内核空间和用户空间切换4次)
若用fwrite,则系统自动分配缓存,则读入此文件只要一次系统调用。


也就是用write要读4次磁盘,而用fwrite则只要读1次磁盘。所以fwrite的效率比write要高4倍。

另外,如果程序对内存有限制,则用write比较好。
系统调用write的效率取决于用户buff的大小和要写入的总数量,如果buff太小,进入内核空间的次数会增加,效率就低下。而fwrite会自动完成缓存分配任务,减少了实际出现的系统调用,所以效率比较高。 

1. 所谓缓冲区,就是一段内存。里面存有内容。fwrite有缓冲,代表当fwrite调用结束之后,它所要求写入文件的内容,可能还有一部分在内存当中,如果要确保写入,需要调用fflush。

fwrite和write的区别_百度知道

fwrite,fflush-----linux编程写文件注意问题(fwrite没有直接写入文件)

2018-10-22 10:13:26

最近项目代码中遇到很多奇怪的问题,比如,在某个程序中用fwrite向配置文件中写入一些数据,而在另一段代码中需要读取该配置文件中的数据,写文件那段程序已经执行完了,但是数据并没有被写入文件,进而导致读文件的代码读不到数据,程序很难按理想的方式运行。这样下来将会导致一些列的问题,我今天就被这个问题纠结了一下午...那么这个问题是什么原因导致的呢,该怎么解决呢?
导致问题的原因是 用fwrite函数写数据的时候,fwrite先将数据写到内存中的缓冲区内,
等程序结束后才会将数据由缓冲区写入文件。所以我遇到的问题原因是整个函数还没有运行完毕,写入的数据还在缓冲区内。
解决办法就只有靠fflush()函数了。

#include<stdio.h>

int fflush(FILE *stream)

该函数的作用就是刷新缓冲区

做法是,在写入的数据在函数结束之前就需要的时候,调用fwrite等函数后,紧接着调用fflush()函数将缓冲区刷新,这样数据就会被立刻写入文件而不用等到程序结束(因为之前的数据都在缓冲区里)。


下面通过一个简单的例子让小伙伴们 加深理解:

int main()
{
    FILE *fp = fopen("./file.txt", "a");
    if(fp == NULL)
    {
        printf("open file err!\n");
        return -1;
    }
    fwrite("hello", 5, 1, fp);
    //fflush(fp);
    close(fp);

    while(1)
    {
        sleep(5);

    }
    return 0;
}


如上程序,当程序一直不退出的时候,虽然已经调用了fwrite但是数据却在缓冲区里,而并不在文件中,这时你可以查看改路径下的file.txt文件,你会发现文件已经建立但是大小为0,如果你在fwrite之后用fflush函数后数据就会立刻写入文件,我总结就这么多,不喜勿喷,希望对小伙伴们有帮助。

-----新增2020.12.08

详细内容:【linux】随机读写之DirectIO|MMAP和DIRECT IO区别_bandaoyu的note-CSDN博客_c++ direct io

fwrite返回后,数据还在CLib buffer,如果这时候进程core掉。这些数据会丢失。没有写到磁盘介质上。当调用fclose的时候,fclose调用会把这些数据刷新到磁盘介质上。除了fclose方法外,还有一个主动刷新操作fflush 函数,不过fflush函数只是把数据从CLib buffer 拷贝到page  cache 中,并没有刷新到磁盘上,从page cache刷新到磁盘上可以通过调用fsync函数完成。 

从上面类子看到,一个常用的fwrite函数过程,基本上历经千辛万苦,数据经过多次copy,才到达目的地。有人心生疑问,这样会提高性能吗,反而会降低性能吧。这个问题先放一放。


over!

---------------------
作者:zhangxiong2532
来源:CSDN
原文:https://blog.csdn.net/zhangxiong2532/article/details/50608898
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 9
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
使用`fread()`和`fwrite()`进行多进程移动同一个文件中的内容需要注意文件指针的位置同步和文件锁的使用。下面是一个示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> int main() { // 打开源文件和目标文件 FILE* src_file = fopen("source.txt", "rb"); FILE* dest_file = fopen("destination.txt", "wb"); // 获取源文件的大小 fseek(src_file, 0, SEEK_END); long file_size = ftell(src_file); fseek(src_file, 0, SEEK_SET); // 创建子进程 pid_t pid = fork(); if (pid == -1) { perror("fork"); exit(1); } else if (pid == 0) { // 子进程负责移动前半部分的内容 fseek(src_file, 0, SEEK_SET); fseek(dest_file, 0, SEEK_SET); size_t read_size; char buffer[1024]; while ((read_size = fread(buffer, 1, sizeof(buffer), src_file)) > 0) { // 写入目标文件 fwrite(buffer, 1, read_size, dest_file); fflush(dest_file); // 获取写入位置并同步文件指针 long current_pos = ftell(dest_file); flockfile(dest_file); fseek(src_file, current_pos, SEEK_SET); funlockfile(dest_file); } exit(0); } else { // 父进程负责移动后半部分的内容 fseek(src_file, file_size / 2, SEEK_SET); fseek(dest_file, file_size / 2, SEEK_SET); size_t read_size; char buffer[1024]; while ((read_size = fread(buffer, 1, sizeof(buffer), src_file)) > 0) { // 写入目标文件 fwrite(buffer, 1, read_size, dest_file); fflush(dest_file); // 获取写入位置并同步文件指针 long current_pos = ftell(dest_file); flockfile(dest_file); fseek(src_file, current_pos, SEEK_SET); funlockfile(dest_file); } // 等待子进程结束 wait(NULL); } // 关闭文件 fclose(src_file); fclose(dest_file); return 0; } ``` 上述代码中,首先打开源文件和目标文件,并获取源文件的大小。然后使用`fork()`创建一个子进程。子进程负责移动源文件的前半部分内容,而父进程负责移动后半部分内容。子进程和父进程使用`fread()`从源文件读取数据,并使用`fwrite()`写入到目标文件中。在写入之前,获取当前的写入位置并同步文件指针,确保两个进程在同一个位置进行读操作。最后,父进程使用`wait()`等待子进程结束,然后关闭文件。 请注意,上述代码中使用了文件锁(`flockfile()`和`funlockfile()`)来同步文件指针的位置,以确保多个进程在移动文件内容时不会相互干扰。同时,需要添加适当的错误处理和边界检查,以确保程序的稳定性和安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值