进程通信

内存映射文件分为两种类型:

  • 持久化内存映射文件

    持久化文件是与磁盘上的源文件相关联的内存映射文件。 当最后一个进程处理完文件时,数据保存到磁盘上的源文件中。 此类内存映射文件适用于处理非常大的源文件。

  • 非持久化内存映射文件

    非持久化文件是不与磁盘上的文件相关联的内存映射文件。 当最后一个进程处理完文件时,数据会丢失,且文件被垃圾回收器回收。 此类文件适合创建共享内存,以进行进程内通信 (IPC)。

进程、视图和管理内存

可以跨多个进程共享内存映射文件。 进程可以映射到相同的内存映射文件,只需使用文件创建进程分配的通用名称即可。

必须创建整个或部分内存映射文件的视图,才能使用内存映射文件。 还可以为内存映射文件的同一部分创建多个视图,从而创建并发内存。 若要让两个视图一直处于并发状态,必须通过同一个内存映射文件创建它们。

如果文件大于可用于内存映射的应用逻辑内存空间(在 32 位计算机中为 2GB),可能也有必要使用多个视图。

视图分为以下两种类型:流访问视图和随机访问视图。 使用流访问视图,可以顺序访问文件;建议对非持久化文件和 IPC 使用这种类型。 随机访问视图是处理持久化文件的首选类型。

由于内存映射文件是通过操作系统的内存管理程序进行访问,因此文件会被自动分区到很多页面,并根据需要进行访问。 无需自行处理内存管理。

 

持久化内存映射文件

CreateFromFile 方法通过磁盘上的现有文件创建内存映射文件。

using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;

class Program
{
    static void Main(string[] args)
    {
        long offset = 0x10000000; // 256 megabytes
        long length = 0x20000000; // 512 megabytes

        // Create the memory-mapped file.
        using (var mmf = MemoryMappedFile.CreateFromFile(@"c:\ExtremelyLargeImage.data", FileMode.Open,"ImgA"))
        {
            // Create a random access view, from the 256th megabyte (the offset)
            // to the 768th megabyte (the offset plus length).
            using (var accessor = mmf.CreateViewAccessor(offset, length))
            {
                int colorSize = Marshal.SizeOf(typeof(MyColor));
                MyColor color;

                // Make changes to the view.
                for (long i = 0; i < length; i += colorSize)
                {
                    accessor.Read(i, out color);
                    color.Brighten(10);
                    accessor.Write(i, ref color);
                }
            }
        }
    }
}

public struct MyColor
{
    public short Red;
    public short Green;
    public short Blue;
    public short Alpha;

    // Make the view brighter.
    public void Brighten(short value)
    {
        Red = (short)Math.Min(short.MaxValue, (int)Red + value);
        Green = (short)Math.Min(short.MaxValue, (int)Green + value);
        Blue = (short)Math.Min(short.MaxValue, (int)Blue + value);
        Alpha = (short)Math.Min(short.MaxValue, (int)Alpha + value);
    }
}

// Assumes another process has created the memory-mapped file.
        using (var mmf = MemoryMappedFile.OpenExisting("ImgA"))
        {
            using (var accessor = mmf.CreateViewAccessor(4000000, 2000000))
            {
                int colorSize = Marshal.SizeOf(typeof(MyColor));
                MyColor color;

                // Make changes to the view.
                for (long i = 0; i < 1500000; i += colorSize)
                {
                    accessor.Read(i, out color);
                    color.Brighten(20);
                    accessor.Write(i, ref color);
                }
            }
        }

  

非持久化内存映射文件

CreateNew 和 CreateOrOpen 方法创建未映射到磁盘上现有文件的内存映射文件。

 

命名管道

在 Windows 中,当尝试使用 Bind() 绑定一个 TCP Socket 时,Defender 会弹窗提示是否允许此程序进行网络连接,只有用户点击允许访问才可放行。我们可以利用添加防火墙规则的办法来绕过这个限制,这个时候我们还有另外的办法就是利用命名管道,命名管道网络通信使用了未加密的SMB协议(端口445)或DCE\RPC(端口135)。在 Windows 中,通常默认允许 SMB 协议 出入站,因此,如果有什么功能或机制可以用于与外部机器进行通信的,SMB 协议 无疑是一种很好的选择。所以我们可以基于命名管道与外部机器进行通信,从而建立控制通道。

posted @ 2020-08-18 20:39  yetsen  阅读(216)  评论(0编辑  收藏  举报