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的同义词

上一篇下一篇

猜你喜欢

热点阅读