Linux系统编程——文件IO——写回实验

1.目的

验证 页缓存 和 写回机制

2.方法

分别用 write,mmap 写入文件,写入后进行sleep,用cat命令查看文件是否有数据,然后断电,重启后查看文件是否有数据。
为了方便测试将 回写时间阈值调整为 50000ms

echo 50000 >  /proc/sys/vm/dirty_writeback_centisecs
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>

#define WRITE_TEST

int main()
{
	int fd;

	fd = open("./tmp", O_RDWR | O_CREAT | O_TRUNC, 0644);
	if (fd < 0) {
		perror("open");
		return -1;
	}

	const char *str = "hello world";

#ifdef WRITE_TEST
	write(fd, str, strlen(str));
	close(fd);

#else
	char *ptr;
	int file_size = 25;

	if (ftruncate(fd, file_size) < 0) {
		perror("ftruncate");
		return -1;
	}

	ptr = mmap(NULL, file_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0);
	if (ptr == MAP_FAILED) {
		perror("mmap");
		return -1;
	}
	close(fd);

	strcpy(ptr, str);
	munmap(ptr, file_size);
#endif

	return 0;
}

3. 结果

重启前另一个进程读文件 重启后进程读文件 重启前查看文件元信息之文件大小 重启后查看元信息
write 有数据 无数据 25字节 0字节
mmap 有数据 无数据 25字节 0字节

3.1 为什么重启前文件有数据,重启后无数据

因为进程读取的数据来自页缓存,页缓存被测试程序写入了数据,但数据没有写回,因为系统有足够的物理内存且未超过写回阈值,
重启后,读文件,文件数据加载到页缓存,程序从页缓存读数据,但是文件本身没有数据,所以显示为空。

文件元数据的情况同上。

4. 使用直接IO测试

write 加上 O_SYNC ,能真实写入,
另外发现 O_SYNC的程序 不会让 其他 页缓存也写回。

O_DIRECT 报参数错误,应该由于是写入数据没有块对齐

mmap:
msync + MS_ASYNC : 不能保证写入
msync + MS_SYNC : 能保证写入

5. 结论

close 不能保证 数据真实写入文件,因为 struct file * 只是 进程和文件的会话,和文件无关,即使一个进程结束会话,其他进程也可能再开启会话,所以 内存中的文件(页缓存)必须保留。
munmap 不能保证 数据真实写入文件,因为 munmap 只是 结束页缓存 映射到一个进程的虚拟空间,于 内存中文件(页缓存)无关。
其他进程能从文件中读取数据,不能保证 数据真实写入文件,因为进程读写文件,是和内存中的文件(页缓存)打交道,与磁盘上的文件无关。

只有 O_SYNC 或 msync + MS_SYNC 或 sync() 等,才能让 脏块加入 IO队列,让pdflush完成写入磁盘。

posted on 2021-08-18 22:28  开心种树  阅读(132)  评论(0编辑  收藏  举报