fsync() 和 write() 在不同的线程中
fsync() and write() in different threads
我正在尝试使用 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 threadn";
close (fd);
return -1;
}
while (1) {
if (write (fd, 'x', 1) < 1)
std::cout << "ERROR write()n";
}
close(fd);
}
问题是:
当我使用文件描述符在主线程以外的其他线程中进行同步时,是否需要锁定不同的线程?当我在没有互斥锁的情况下测试我的程序时,它没有问题。当我阅读 fsync 的 man 描述时,它没有不同的线程。
如果fsync
需要时间,甚至有时在很短的时间内阻塞的事实是一个问题,那么你很可能做错了什么。
通常,您根本不想打电话给fsync
。这样做是一种严重的反优化,只有在必须确保数据已写出的情况下,才会想要这样做1.但是,在这种情况下,您绝对希望fsync
阻止,这不仅按预期工作,而且是必要的。
只有当fsync
回来时,你才知道它已经完成了它的任务。您知道操作系统已尽最大努力确保数据已写入,只有这样才能安全地继续。如果你把它卸载到后台线程,你也可以不调用fsync
,因为你不知道什么时候可以安全地假设数据已经写入。
如果启动写入是你的主要目标,则可以在 Linux 下使用 sync_file_range
(异步运行),然后在一段时间后调用fsync
。跟进fsync
的原因既是为了确保完成写入,也是为了确保sync_file_range
不会更新元数据,因此除非您严格覆盖文件中已分配的数据,否则即使数据在磁盘上,您的写入也可能在崩溃的情况下不可见(我无法想象这是怎么发生的,因为为文件分配更多扇区必然意味着必须修改元数据, 但手册页明确警告可能会发生这种情况)。
<小时 />
1fsync
函数仍然不能(也不能)保证数据位于永久存储上,它可能仍在缓存层次结构中的某个位置,例如控制器或磁盘的写入缓存。
除非您需要线程进行其他操作,否则我建议您使用异步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);
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- c++中的线程池
- 线程之间的布尔停止信号
- 为什么std::async使用同一个线程运行函数
- 用于矢量处理的多个线程
- C++为线程工作动态地分割例程
- fsync() 和 write() 在不同的线程中