Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在写入共享内存时,托管进程能否终止?_C#_.net_Shared Memory_Memory Mapped Files_Cer - Fatal编程技术网

C# 在写入共享内存时,托管进程能否终止?

C# 在写入共享内存时,托管进程能否终止?,c#,.net,shared-memory,memory-mapped-files,cer,C#,.net,Shared Memory,Memory Mapped Files,Cer,我有几个(managed/.NET)进程通过一个环形缓冲区进行通信,该缓冲区通过MemoryMappedFile类保存在共享内存中(只是内存未映射文件)。我从SafeBuffer引用源知道,将结构写入该内存是由CER(受限执行区域)保护的,但如果写入过程在这样做时被操作系统异常终止,该怎么办?这会不会导致结构只被部分写入 struct MyStruct { public int A; public int B; public float C;

我有几个(managed/.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标志),进程是否受到保护,不受异常终止的影响。

是的,进程可以随时停止

SafeBuffer.Write
方法最终调用

[MethodImpl(MethodImplOptions.InternalCall)]
[ResourceExposure(ResourceScope.None)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
private static extern void StructureToPtrNative(/*ref T*/ TypedReference structure, byte* ptr, uint sizeofT);
这基本上是一个
memcpy(ptr,structure,sizeofT)
。由于未对齐的写除了字节之外永远不会是原子的,如果您的进程在写入一个值时在中间终止,则会遇到问题。
当通过
TerminateProcess
或未处理的异常以艰难的方式终止某个进程时,不会执行CER或相关内容。在这种情况下,没有适当的管理关机发生,并且您的应用程序可以在重要事务的中间停止。您的共享内存数据结构将处于孤立状态,您可能使用的任何锁都将返回
WaitForSingleObject
WAIT\u中的下一个服务员。这样,Windows会告诉您进程在获取锁时已死亡,您需要恢复上一个写入程序所做的更改

不,它是一个操作系统对象,它知道RAM页面已映射。如果操作系统也不能完成任务,您可能会丢失数据,例如断电。@Hans,我添加了一个代码示例来演示我的问题。对我来说,这不是关于丢失数据,而是关于写入数据的进程在写入过程中被终止时部分写入的数据。如果您不能确保Write()在程序崩溃/终止之前成功完成,那么您当然什么都不知道。Write()不是原子的。我想你会发现在MMF中指定一个字节来表示“忙写”很有用。在写入之前将其设置为1,在写入之后将其设置为0,现在您有了一个事实。为什么其他进程会在任何时候访问一个区域(大于64位)并假设一致性?听起来好像您有一个损坏的协议(或者需要存在的不存在的协议),MMF不一定对进程互操作有用。事实上,它是最不实用的用法之一。