我正在尝试使用 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);
}
Run Code Online (Sandbox Code Playgroud)
问题是:
当我使用文件描述符在除主线程之外的其他线程中进行 fsync 时,是否需要锁定不同的线程?当我在没有互斥体的情况下测试我的程序时,它没有问题。当我阅读 fsync 的 man 描述时,它没有针对不同线程的任何内容。
fsync如果需要时间甚至有时会在很短的时间内阻塞这一事实是一个问题,那么您很可能做错了什么。
fsync通常,您根本不想打电话。这样做是一种严重的反优化行为,只有在必须确保数据已被写出时才愿意这样做1。然而,在这种情况下,你绝对想要 fsync阻止,这不仅是按预期工作,而且是必要的。
只有当fsync它返回时,你才知道它已经完成了它的任务。您知道操作系统已尽最大努力确保数据已写入,只有这样才能安全地继续。如果您将其卸载到后台线程,您也可以不调用fsync,因为您不知道何时可以安全地假设数据已写入。
如果启动写入是您的主要目标,您可以在 Linux 下使用(异步运行),然后稍后sync_file_range调用。fsync跟进的原因fsync既是为了确保写入完成,也是为了sync_file_range不更新元数据,因此除非您严格覆盖文件中已分配的数据,否则在崩溃的情况下您的写入可能不可见,即使数据位于磁盘上(我无法想象这会如何发生,因为向文件分配更多扇区必然意味着必须修改元数据,但联机帮助页明确警告这种情况可能会发生)。
fsync函数仍然不(也不能)保证数据位于永久存储上,它可能仍然位于缓存层次结构中的某个位置,例如控制器或磁盘的写入缓存。