CreateFileMapping, MapViewOfFile 实现文件共享

 

using System;

using System.IO;

using System.Runtime.InteropServices;

using System.Text;

using System.Threading;

 

namespace Mem1

{

    class Program

    {

        static void Main(string[] args)

        {

            Mem m = new Mem();

 

            string text = File.ReadAllText(@"aa.txt", Encoding.Default);

            m.Write(text);

            string st = m.Read();

            //finally

            m.Close();

        }

    }

 

 

 

    class Mem

    {

        //full defination

        [Flags]

        public enum FileMapAccess : uint

        {

            FileMapCopy = 0x0001,

            FileMapWrite = 0x0002,

            FileMapRead = 0x0004,

            FileMapAllAccess = 0x001F,

            fileMapExecute = 0x0020,

        }

 

        [Flags]

        enum FileMapProtection : uint

        {

            PageReadonly = 0x02,

            PageReadWrite = 0x04,

            PageWriteCopy = 0x08,

            PageExecuteRead = 0x20,

            PageExecuteReadWrite = 0x40,

            SectionCommit = 0x8000000,

            SectionImage = 0x1000000,

            SectionNoCache = 0x10000000,

            SectionReserve = 0x4000000,

        }

       

        const int INVALID_HANDLE_VALUE = -1;

 

        private Semaphore m_Write; //可写的信号

        private Semaphore m_Read; //可读的信号

        private IntPtr handle;     //文件句柄

        private IntPtr addr;       //共享内存地址

        private const uint mapLength = 10240;            //共享内存长,如果要是超长的话,应另外处理,最好是分配足够的内存

 

        [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")]

        private static extern IntPtr CreateFileMapping(

            IntPtr hFile,

            UInt32 lpAttributes,

            FileMapProtection flProtect,

            UInt32 dwMaximumSizeHigh,

            UInt32 dwMaximumSizeLow,

            string lpName);

 

        [DllImport("Kernel32.dll", EntryPoint = "OpenFileMapping")]

        private static extern IntPtr OpenFileMapping(

            UInt32 dwDesiredAccess,

            int bInheritHandle,

            string lpName);

 

 

        [DllImport("Kernel32.dll", EntryPoint = "MapViewOfFile")]

        private static extern IntPtr MapViewOfFile(

            IntPtr hFileMappingObject,

            FileMapAccess dwDesiredAccess,

            UInt32 dwFileOffsetHight,

            UInt32 dwFileOffsetLow,

            UInt32 dwNumberOfBytesToMap);

 

        [DllImport("Kernel32.dll", EntryPoint = "UnmapViewOfFile")]

        private static extern int UnmapViewOfFile(IntPtr lpBaseAddress);

 

        [DllImport("Kernel32.dll", EntryPoint = "CloseHandle")]

        private static extern int CloseHandle(IntPtr hObject);

 

 

 

        public void Write(string text)

        {

            Console.WriteLine("write");

            m_Write = new Semaphore(1, 1, "WriteMap");

            m_Read = new Semaphore(0, 1, "ReadMap");

            IntPtr hFile = new IntPtr(INVALID_HANDLE_VALUE);

            handle = CreateFileMapping(hFile, 0, FileMapProtection.PageReadWrite, 0, mapLength, "shareMemory");

            addr = MapViewOfFile(handle, FileMapAccess.FileMapAllAccess, 0, 0, 0);

 

 

            m_Write.WaitOne();

            byte[] sendStr = Encoding.Unicode.GetBytes(text + '\0');

 

            if (sendStr.Length < mapLength) //4G max limit on FAT32 ?

                StrCopy(sendStr, addr);

            else throw new AccessViolationException("...");

            m_Read.Release();

 

        }

 

 

        public string Read()

        {

            Console.WriteLine("read");

            m_Write = Semaphore.OpenExisting("WriteMap");

            m_Read = Semaphore.OpenExisting("ReadMap");

            handle = OpenFileMapping(0x0002, 0, "shareMemory");

 

 

            m_Read.WaitOne();

            IntPtr str = MapViewOfFile(handle, FileMapAccess.FileMapAllAccess, 0, 0, 0);

            string s = Pop(str);

            m_Write.Release();

 

            return s;

        }

 

 

        static unsafe string Pop(IntPtr src)

        {

            byte[] byteDst = new byte[mapLength];

            fixed (byte* pSrc = byteDst)

            {

                byte* pSrc1 = (byte*)src;

                byte* pDest1 = pSrc;

                for (int i = 0; i < byteDst.Length; i++)

                {

                    *pDest1 = *pSrc1;

                    pSrc1++;

                    pDest1++;

               }

            }

 

            UnicodeEncoding encoding = new UnicodeEncoding();

            string constructedstring = encoding.GetString(byteDst);

 

            return constructedstring;

        }

 

 

        static unsafe void StrCopy(byte[] byteSrc, IntPtr dst)

        {

            fixed (byte* pSrc = byteSrc)

            {

                byte* pDst = (byte*)dst;

                byte* psrc = pSrc;

                for (int i = 0; i < byteSrc.Length; i++)

                {

                    *pDst = *psrc;

                    pDst++;

                    psrc++;

                }

            }

        }

 

 

        public void Close()

        {

            UnmapViewOfFile(addr);

            CloseHandle(handle);

        }

 

    }

 

}

去掉原文(找不到从哪里看的了,可以G到很多相似结果)一些注释。 代码改了一下, 用了pinvoke的定义, 全部代码win7下测试可用。

大概核心意思就是放到内存里读。 C#里没有strcpy, 需要用fixed关键字来处理一下。

然后字符写入读出的编码一致就可以支持中文了。

另外一定要释放资源, 否则会变得很慢。

 

posted on 2009-11-27 17:45  无法显示此网页  阅读(2685)  评论(0编辑  收藏  举报

导航