【发布时间】:2018-07-28 06:59:03
【问题描述】:
我有几个(托管/.NET)进程通过一个环形缓冲区进行通信,该缓冲区通过 MemoryMappedFile 类保存在共享内存中(只是内存没有文件映射)。我从 SafeBuffer 参考源知道,将结构写入该内存受到 CER(约束执行区域)的保护,但是如果写入过程在这样做时被操作系统异常终止怎么办?会不会导致结构只被部分写入?
struct MyStruct
{
public int A;
public int B;
public float C;
}
static void Main(string[] args)
{
var mappedFile = MemoryMappedFile.CreateOrOpen("MyName", 10224);
var accessor = mappedFile.CreateViewAccessor(0, 1024);
MyStruct myStruct;
myStruct.A = 10;
myStruct.B = 20;
myStruct.C = 42f;
// Assuming the process gets terminated during the following write operation.
// Is that even possible? If it is possible what are the guarantees
// in regards to data consistency? Transactional? Partially written?
accessor.Write(0, ref myStruct);
DoOtherStuff(); ...
}
很难模拟/测试这个问题是否真的存在,因为写入内存非常快。但是,这肯定会导致我的共享内存布局严重不一致,并且有必要通过校验和或某种页面翻转来解决这个问题。
更新:
查看第 1053 行
它基本上归结为一个问题,当在 CER 块中执行代码时(设置了 Consistency.WillNotCorruptState 标志),进程是否受到异常终止的保护。
【问题讨论】:
-
不,它是一个 OS 对象,它知道 RAM 页面已被映射。如果操作系统也无法完成工作,您可能会丢失数据,例如断电。
-
@Hans,我添加了一个代码示例来演示我的问题/问题。对我来说,这与丢失数据无关,而是在写入数据的进程在写入时终止时部分写入的数据。
-
如果你不能确定在程序崩溃/终止之前 Write() 是否成功完成,那么你当然什么都不知道。 Write() 不是原子的。我怀疑您会发现在 MMF 中指定一个指示“忙于写入”的字节很有用。在写入之前将其设置为 1,之后设置为 0,现在您有了一个事实。
-
为什么其他进程在任何时候访问一个区域(大于64位)并假设一致性?听起来你有一个损坏的协议(或者一个不存在的协议需要存在)
-
MMF 不一定对进程互操作有用。事实上,这是它最不实用的用途之一。
标签: c# .net shared-memory memory-mapped-files cer