fsync()和write()在不同的线程中

时间:2014-03-31 11:10:50

标签: c++ c linux io

我正在尝试使用fsync()和write()编写程序,但fsync需要时间来同步数据,但我还没有时间等待。我为fsync()再做了一个线程 这是我的代码:

#include <thread>
void thread_func(int fd) {
    while (1) {
       if(fsync(fd) != 0)
           std::cout << "ERROR fsync()\n";
       usleep(100);
    }
}
int main () {
    int fd = open ("device", O_RDWR | O_NONBLOCK);
    if (fd < 0) {
        std::cout << "ERROR: open()\n";
        return -1;
    }
    std::thread *thr = new std::thread (thread_func, fd);
    if (thr == nullptr) {
       std::cout << "Cannot create thread\n";
       close (fd);
       return -1;
    }
    while (1) {
       if (write (fd, 'x', 1) < 1)
          std::cout << "ERROR write()\n";
    }
    close(fd);
}

问题是:

当我使用文件描述符到主要的其他线程中的fsync时,是否需要锁定不同的线程? 当我测试我的程序没有互斥时它没有问题。当我读fsync的man description时,它对于不同的线程没有任何帮助。

2 个答案:

答案 0 :(得分:3)

如果fsync花费时间甚至有时会在很短的时间内阻塞这一事实是一个问题,那么你很可能做错了。

通常情况下,您根本不想要致电fsync。这样做是一种严重的反优化,如果必须确保数据已写出 1 ,那么人们只会想要这样做。但是,在这种情况下,您绝对想要 fsync来阻止,这不仅符合预期,而且是必要的。
只有当fsync返回时,您才知道它已完成任务。您知道操作系统已尽最大努力确保已写入数据,只有这样才能继续安全。如果你将它卸载到后台线程,你也可以不调用fsync,因为你不知道什么时候可以安全地假设数据被写入。

如果启动写入是您的主要目标,则在Linux(异步运行)下使用sync_file_range,然后在稍后调用fsync。跟进fsync的原因是确保写入完成,以及sync_file_range不更新元数据的事实,因此除非您严格覆盖文件中已经分配的数据,否则您的写入可能即使数据在磁盘上也不会出现崩溃(我无法想象,如果将更多扇区分配给文件必然意味着必须修改元数据,那么可能会发生这种情况,但是联机帮助页明确警告可以发生)。

<小时/> 1 fsync函数仍然没有(也不能)保证数据在永久存储器上,它可能仍然在缓存层次结构中的某个位置,例如控制器或磁盘的写入缓存。

答案 1 :(得分:1)

除非你需要线程用于其他东西,否则我建议你使用异步I / O aio库:

struct aiocb fsync_cb = {
      .aio_fildes = fd
    , .aio_sigevent = {
        .sigev_notify = SIGEV_NONE
    }
}

aio_fsync(O_SYNC, &fsync_cb);

还有write的等效变体。

struct aiocb write_cb = {
      .aio_fildes = fd
    , .aio_buf = buffer
    , .aio_nbytes = nbytes
    , .aio_offset = offset
    , .aio_sigevent = {
        .sigev_notify = SIGEV_NONE
    }
}

aio_write(&write_cb);

如果您选择不作任何通知,那么您必须在某个时间点检查/等待完成:

while (aio_error(&write_cb) == EINPROGRESS);