测试过a+的时候,发现两个进程同时开一个文件,
1,即使不fclose,数据还是会往硬盘写。
2,发现1K的时候数据会从clib写入系统的PAGE_BUF.
3,从page_buf往硬盘写的时机是kernel有一个pflush线程按照一定的算法去刷新。
比如几个扇区挨的近的会在一起刷。
两个进程同时运行写一个文件,他们会穿插着写,而且穿插单位是1K。
include "stdio.h"
main()
{
FILE *fp;
int i=0;
char buf[256]="hit33333\n";
fp=fopen("./writefile.txt","a+");
while(1)
{
i++;
fwrite(buf,1,256,fp);
sleep(1);
printf("i si %d\n",i);
if(i==600)
break;
}
fclose(fp);
}
include "stdio.h"
main()
{
FILE *fp;
int i=0;
char buf[256]="love33333\n";
fp=fopen("./writefile.txt","a+");
while(1)
{
i++;
fwrite(buf,1,256,fp);
sleep(1);
printf("j si %d\n",i);
if(i==600)
break;
}
fclose(fp);
}
会发现打印是两个进程穿插。比如 i is 1,j is 1,i is 2 ,j is 2.
但是写入flash的数据是hit33333
hit33333
hit33333
hit33333
love3333
love3333
love3333
love3333
交替。
而且PAGE BUf是每4K刷一次!!!
文件大小上是每4K变一次。
如果加了fflush();
则PAGE BUF则是每次都会到设备。
从网络上有的说只会写到内核缓冲器。是fsync才会写到设备。
但是从fflush()测试的结果看,每次这个文件都是8字节增长,而且在不同进程中读,则发现是实时更新。
如果没有fflush,则是每4K才更新,导致另外一个进程的读会一开始都是空的。不同步。
这也说明一个问题,一个文件在内核中,当都是追加写的时候,用了同一个内核心缓冲,但是读的时候,是另一个缓冲,如果要按照顺序写,该如何处理。
加flush.
同时测试如下:
main()
{
FILE * fd;
struct stat sb;
char buf[0x8000];
fd=fopen("./testtext","wb+");
fwrite(buf,4092,1,fd);
// fseek(fd,0,SEEK_END);
// ftell(fd);
// fseek(fd,0,SEEK_SET);
// fread(buf2,4092,1,fd);
if(stat("./testtext", &sb) == -1)
{
printf("error!!\n");
return -1;
}
printf("the size is %d\n",sb.st_size);
sleep(10);
fwrite(buf,1,5,fd);
// fflush(fd);
// sleep(10);
if(stat("./testtext", &sb) == -1)
{
printf("error!!");
return -1;
}
printf("the22 size is %d\n",sb.st_size);
}
答案是0,4096.
如果开了fseek(fd,0,SEEK_END);答案是4092,4096.
应该是内核区域并刷到了硬盘,但是内核数据还是在,等到再刷5个字节的时候,再次将所有数据都丢到硬盘。
测试过,第一次写的时候4K会全部丢进硬盘,但是第二次写一定要超过4K,比如4K+1,所以这里一定是5,如果是4,答案将是4092,4092.
如果开了ftell(fd);答案是4092,4092.
应该是从内核区域并刷到了硬盘.而且内核数据被清除了,所以再刷5个字节的时候,因为内核还只有5个,不会再丢到内核区域。
如果开了fread(fd,0,SEEK_END),则一定会写到硬盘。而且内核,和SEEK一个道理。
分析这些,主要原因还是为了同步。
从上面的分析可以看出。
如果两个线程一个读,一个写,则需要同步。两个写,也是必须同步。