我正在尝试使用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时,它对于不同的线程没有任何帮助。
答案 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);