内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文件,就 像操作进程空间里的地址一样了,比如使用c语言的memcpy等内存操作的函数。这种方法能够很好的应用在需要频繁处理一个文件或者是一个大文件的场合, 这种方式处理IO效率比普通IO效率要高

共享内存是内存映射文件的一种特殊情况,内存映射的是一块内存,而非磁盘上的文件。共享内存的主语是进程(Process),操作系统默认会给每一 个进程分配一个内存空间,每一个进程只允许访问操作系统分配给它的哪一段内存,而不能访问其他进程的。而有时候需要在不同进程之间访问同一段内存,怎么办 呢?操作系统给出了创建访问共享内存的API,需要共享内存的进程可以通过这一组定义好的API来访问多个进程之间共有的内存,各个进程访问这一段内存就 像访问一个硬盘上的文件一样。而.Net 4.0中引入了System.IO. MemoryMappedFiles命名空间,这个命名空间的类对windows 共享内存相关API做了封装,使.Net程序员可以更方便的使用内存映射文件。

在C#中使用共享内存。以下App1的代码让用户输入一行文本到共享内存中;App2不停的刷新控制台,输出最新的共享内存内容;App3实现的功能和App2相同,但读取方法不同。

App1代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using System.IO;
 
//引用内存映射文件命名空间
using System.IO.MemoryMappedFiles;
 
namespace App1
{
    class Program
    {
        static void Main(string[] args)
        {
            long capacity = 1<<10<<10;
 
            //创建或者打开共享内存
            using (var mmf = MemoryMappedFile.CreateOrOpen("testMmf", capacity, MemoryMappedFileAccess.ReadWrite))
            {
                //通过MemoryMappedFile的CreateViewAccssor方法获得共享内存的访问器
                var viewAccessor = mmf.CreateViewAccessor(0, capacity);
                //循环写入,使在这个进程中可以向共享内存中写入不同的字符串值
                while (true)
                {
                    Console.WriteLine("请输入一行要写入共享内存的文字:");
 
                    string input = Console.ReadLine();
 
                    //向共享内存开始位置写入字符串的长度
                    viewAccessor.Write(0, input.Length);
 
                    //向共享内存4位置写入字符
                    viewAccessor.WriteArray<char>(4, input.ToArray(), 0, input.Length);
                }
 
            }
             
        }
    }
}

App2代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
 
//引用使用内存映射文件需要的命名空间
using System.IO.MemoryMappedFiles;
 
namespace App2
{
    class Program
    {
        static void Main(string[] args)
        {
              long capacity = 1<<10<<10;
 
              using (var mmf = MemoryMappedFile.OpenExisting("testMmf"))
              {
                  MemoryMappedViewAccessor viewAccessor = mmf.CreateViewAccessor(0, capacity);
 
                  //循环刷新共享内存字符串的值
                  while (true)
                  {
                      //读取字符长度
                      int strLength = viewAccessor.ReadInt32(0);                     
                      char[] charsInMMf = new char[strLength];
                      //读取字符
                      viewAccessor.ReadArray<char>(4, charsInMMf, 0, strLength);
                      Console.Clear();
                      Console.Write(charsInMMf);
                      Console.Write("\r");
                      Thread.Sleep(200);
                  }
              }
        }
    }
}

App3代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using System.IO.MemoryMappedFiles;
using System.IO;
 
namespace App3
{
    class Program
    {
        static void Main(string[] args)
        {
            long capacity = 1 << 10 << 10;
            //打开共享内存
            using (var mmf = MemoryMappedFile.OpenExisting("testMmf"))
            {
                //使用CreateViewStream方法返回stream实例
                using (var mmViewStream = mmf.CreateViewStream(0, capacity))
                {
                    //这里要制定Unicode编码否则会出问题
                    using (BinaryReader rdr = new BinaryReader(mmViewStream,Encoding.Unicode))
                    {
                        while (true)
                        {
                            mmViewStream.Seek(0, SeekOrigin.Begin);
 
                            int length = rdr.ReadInt32();
 
                            char[] chars = rdr.ReadChars(length);
 
                            Console.Write(chars);
                            Console.Write("\r");
 
                            System.Threading.Thread.Sleep(200);
                            Console.Clear();
                        }
                    }
                }
            }
        }
    }
}

单这么写也许大家不理解内存映射文件的使用,下一篇想写一篇介绍内存映射文件应用实例的文章。

相关随笔: .Net那点事儿系列:System.IO之windows文件操作
.Net那点事儿系列:System.IO之Stream

System.IO之内存映射文件共享内存

System.IO之使用管道在进程间通信 (System.IO.Pipes使用)

System.IO系列:局域网内多线程使用命名管道在进程之间通信实例

System.IO之内存映射文件共享内存的更多相关文章

  1. c#实现内存映射文件共享内存

    原文:http://blog.csdn.net/wangtiewei/article/details/51112668 内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文件, ...

  2. kmalloc分配物理内存与高端内存映射--Linux内存管理(十八)

    1 前景回顾 1.1 内核映射区 尽管vmalloc函数族可用于从高端内存域向内核映射页帧(这些在内核空间中通常是无法直接看到的), 但这并不是这些函数的实际用途. 重要的是强调以下事实 : 内核提供 ...

  3. 使用Java内存映射(Memory-Mapped Files)处理大文件

    >>NIO中的内存映射 (1)什么是内存映射文件内存映射文件,是由一个文件到一块内存的映射,可以理解为将一个文件映射到进程地址,然后可以通过操作内存来访问文件数据.说白了就是使用虚拟内存将 ...

  4. 《Java核心技术卷二》笔记(二)文件操作和内存映射文件

    文件操作 上一篇已经总结了流操作,其中也包括文件的读写.文件系统除了读写以为还有很多其他的操作,如复制.移动.删除.目录浏览.属性读写等.在Java7之前,一直使用File类用于文件的操作.Java7 ...

  5. Java NIO内存映射---上G大文件处理(转)

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文主要讲了java中内存映射的原理及过程,与传统IO进行了对比,最后,用实例说明了结果 ...

  6. ZT 匿名内存映射

    mmap函数使用 分类: Linux/Unix C/C++ 2008-01-22 17:03 6089人阅读 评论(1) 收藏 举报 unix编程null网络 UNIX网络编程第二卷进程间通信对mma ...

  7. linux编程之内存映射

    一.概述                                                   内存映射是在调用进程的虚拟地址空间创建一个新的内存映射. 内存映射分为2种: 1.文件映射 ...

  8. Win 内存映射和堆栈

    内存映射和堆栈 内存映射文件 内存映射文件可以用于3个不同的目的: 系统使用内存映射文件,以便加载和执行.exe和DLL文件.这可以大大节省页文件空间和应用程序启动运行所需的时间. 可以使用内存映射文 ...

  9. 【VS开发】内存映射文件3

    内存映射文件 内存映射文件,是由一个文件到一块内存的映射.Win32提供了允许应用程序把文件映射到一个进程的函数 (CreateFileMapping).内存映射文件与虚拟内存有些类似,通过内存映射文 ...

随机推荐

  1. 静态链表 C语言描述

    静态链表1.下标为0的游标存放最后存放数据节点的游标,即是第一个没有存放元素(备用链表)的下标2.最后一个的节点存放第一个由数值得下标3.第一个和最后一个都不存放数据 即是备用链表的第一个的下标 4. ...

  2. MySQL数据库获取多个汉字拼音的首字母函数

    需求简介:最近的一个项目,想实现如下图所示的显示效果.很明显,如果能够获取对应的汉字词组中每个汉字的拼音首字母就可以实现了,如果是固定的几组汉字,人为的拼一下就可以 了,不过项目中有多处功能需要这个效 ...

  3. 华为OJ平台——超长正整数相加

    题目描述: 请设计一个算法完成两个超长正整数的加法. 输入 输入两个字符串数字 输出 输出相加后的结果,string型 样例输入 99999999999999999999999999999999999 ...

  4. ref传递

    下面通过一个排序的小栗子来分析ref传递: static void Main(string[] args) { ,,,,}; int num; Console.WriteLine("请输入您 ...

  5. wcscpy wcscpy_s strcpy strcpy_s的区别

    原型声明:extern char *strcpy(char *dest,const char *src); 头文件:string.h 功能:把从src地址开始且含有NULL结束符的字符串赋值到以des ...

  6. css透明属性

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. python os模块sys模块常用方法

    官方文档看这里 https://docs.python.org/3.5/library/os.html http://www.cnblogs.com/wupeiqi/articles/5501365. ...

  8. java值得注意的几个问题

    1.一个源文件中只能有一个类是public的,其他的都是默认权限的: 2.一个类只能作为public或者默认权限(就是没有修饰符的意思): 3.源文件的public类的名字必须要跟文件名保持一致,否则 ...

  9. c#获取多个List<class>合并、并将相同条件下的值累计sum

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  10. Google -We’re Sorry....

    Author:KillerLegend From:http://www.cnblogs.com/killerlegend/p/3734840.html Date:2014.5.18 一大清早 一大早起 ...