File I/O 同步I/O
2019-08-12 本文已影响0人
无无吴
fsync() and fdatasync()
#include <unistd.h>
int fsync(int fd);
对fsync()的调用确保将与文件描述符fd映射的文件相关的所有脏数据写回磁盘。文件描述符FD必须打开以便写入。函数调用将写回数据和元数据,例如创建时间戳和inode中包含的其他属性。在硬盘确认数据和元数据在磁盘上之前,它不会返回。
以上应该适用于没有写入缓存的硬盘。
如果是是有写入缓存的硬盘,则应该用fdatasync()
#include <unistd.h>
int fdatasync(int fd);
此系统调用与fsync()执行相同的操作,只不过它只刷新将来正确访问文件所需的数据和元数据。并且性能更好。
int ret;
ret = fsync(fd);
if(ret == -1)
/*error*/
int ret;
ret = fdatasync(fd);
if(ret == -1)
/*error*/
这两个函数都不保证包含该文件的任何更新目录条目都同步到磁盘。这意味着,如果最近更新了文件的链接,文件的数据可能会成功到达磁盘,但关联的目录条目并没有,使文件无法访问。为了确保目录条目的任何更新也提交到磁盘,还必须调用fsync() 针对文件目录打开的文件描述符。
POSIX要求是实现fsync(),fdatasync()是可选的。
对于任何常见Linux文件系统上的常规文件,都应该始终实现fsync()系统调用。
但是,非典型的文件类型(可能是那些没有元数据可同步化的文件类型)或奇怪的文件系统可能只实现fdatasync()。
所以为了兼容应该这样用:
if (fsync (fd) == −1) {
/*
* We prefer fsync(), but let's try fdatasync()
* if fsync() fails, just in case.
*/
if (errno == EINVAL) {
if (fdatasync (fd) == −1)
perror ("fdatasync");
} else
perror ("fsync");
}
sync()
旧式sync()系统调用用于将所有缓冲区同步到磁盘:
#include <unistd.h>
void sync(void)
该函数没有参数,也没有返回值。它总是成功的,返回时,所有缓冲区数据和元数据都保证驻留在磁盘上。
请注意,在繁忙的系统上完成sync()可能需要几分钟或更长时间。
标志位O_SYNC
int fd;
fd = open(file, O_WRONLY | O_SYNC);
if(fd == -1){
perror("open);
return -1;
}
O_sync标志强制执行这种关系,确保对write()的调用执行同步I/O。
只有在用尽了所有可能的选择后才能使用同步I/O。
O_DSYNC and O_RSYNC
在Linux上,这些标志被定义为O_sync的同义词