首页 > 解决方案 > Linux 文件写入页面缓冲区和多线程 CPU 缓存

问题描述

一个线程写入 FD 的数据是否立即可供另一个线程使用?下面是解释这个问题的 C++ 代码。

操作系统 = 红帽 Linux

文件打开代码

//Below are global variables
int fileFd_A = open(fileName_A, O_RDWR | O_CREAT, S_IREAD | S_IWRITE | S_IRGRP | S_IROTH);
int fileFd_B = open(fileName_B, O_RDWR | O_CREAT, S_IREAD | S_IWRITE | S_IRGRP | S_IROTH);

std::atomic<int64_t> lastFileAPos = {-1};
std::atomic<int64_t> lastFileBPos = {-1};

const int WriteSz = 16;

在 Writer 线程 (posix) 中完成文件写入

//Below called in a loop
int64_t fileAPosition  = tell(fileFd_A);
int64_t fileBPosition  = tell(fileFd_B);

write(fileFd_A , pBufA, WriteSz);
write(fileFd_B , pBufB, WriteSz);//Assume all writes are successful

lastFileAPos.store(fileAPosition , std::memory_order_relaxed);
lastFileBPos.store(fileBPosition , std::memory_order_relaxed);

在不同的 posix 线程中完成文件读取,

//Below called in a loop (assume lastFileAPos/lastFileBPos == -1 case filtered out out before calling below)
int readSzA = pread(fileFd_A, bufferA, WriteSz, (off_t)lastFileAPos.load(std::memory_order_relaxed));
int readSzB = pread(fileFd_B, bufferB, WriteSz, (off_t)lastFileBPos.load(std::memory_order_relaxed));

现在阅读器线程是否可能无法读取在某些迭代中写入 lastFileAPos 或/和 lastFileBPos 的最新数据?
即 readSzA < WriteSz 或 readSzB < WriteSz(或两者)?
是否可能 readSzA < WriteSz 和 readSzB == WriteSz ?

我的感觉是,由于某些写入在写入线程 CPU 缓存中(仍未发送到主内存),读取线程 CPU 可能无法立即读取它们(因此某些读取可能会失败)。
如果是这种情况(即某些读取可能会失败),是否会使用 memory_order_release(for store) 和 memory_order_acquire(for load) 而不是 memory_order_relaxed 解决此问题?
即调用“lastFileAPos.load(std::memory_order_acquire)”将确保在“lastFileAPos.store(fileAPosition,std::memory_order_release)”可见之前所有内存写入(包括写入内核写入缓冲区)。所以保证 readSzA == WriteSz 和 readSzB == WriteSz

标签: c++linuxmultithreading

解决方案


推荐阅读