原文:C# 进程间通信(共享内存)

进程间通信的方式有很多,常用的方式有:

1.共享内存(内存映射文件,共享内存DLL)。

2.命名管道和匿名管道。

3.发送消息

本文是记录共享内存的方式进行进程间通信,首先要建立一个进程间共享的内存地址,创建好共享内存地址后,一个进程向地址中写入数据,另外的进程从地址中读取数据。

在数据的读写的过程中要进行进程间的同步。

进程间数据同步可以有以下的方式

1. 互斥量Mutex

2. 信号量Semaphore

3. 事件Event

本文中进程间的同步采用 信号量Semaphore的方式同步思想类似于操作系统中生产者和消费者问题的处理方式。

在A进程中创建共享内存,并开启一个线程用来读取B进程向共享内存中写入的数据,定义两个信号量进行读写互斥同步

A进程中的程序代码

using System;

using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Runtime.InteropServices;using System.Threading;using System.Diagnostics;namespace AppOne{    public partial class AppOneMain : Form    {        const int INVALID_HANDLE_VALUE = -;        const int PAGE_READWRITE = 0x04;        [DllImport("User32.dll")]        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);        [DllImport("User32.dll")]        private static extern bool SetForegroundWindow(IntPtr hWnd);        //共享内存        [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")]        private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile,         UInt32 lpAttributes,//LPSECURITY_ATTRIBUTES lpAttributes,  //         UInt32 flProtect,//DWORD flProtect         UInt32 dwMaximumSizeHigh,//DWORD dwMaximumSizeHigh,         UInt32 dwMaximumSizeLow,//DWORD dwMaximumSizeLow,         string lpName//LPCTSTR lpName         );        [DllImport("Kernel32.dll", EntryPoint = "OpenFileMapping")]        private static extern IntPtr OpenFileMapping(         UInt32 dwDesiredAccess,//DWORD dwDesiredAccess,         int bInheritHandle,//BOOL bInheritHandle,         string lpName//LPCTSTR lpName         );        const int FILE_MAP_ALL_ACCESS = 0x0002;        const int FILE_MAP_WRITE = 0x0002;        [DllImport("Kernel32.dll", EntryPoint = "MapViewOfFile")]        private static extern IntPtr MapViewOfFile(         IntPtr hFileMappingObject,//HANDLE hFileMappingObject,         UInt32 dwDesiredAccess,//DWORD dwDesiredAccess         UInt32 dwFileOffsetHight,//DWORD dwFileOffsetHigh,         UInt32 dwFileOffsetLow,//DWORD dwFileOffsetLow,         UInt32 dwNumberOfBytesToMap//SIZE_T 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);        private Semaphore m_Write;  //可写的信号        private Semaphore m_Read;  //可读的信号        private IntPtr handle;     //文件句柄        private IntPtr addr;       //共享内存地址        uint mapLength;            //共享内存长        //线程用来读取数据        Thread threadRed;        public AppOneMain()        {            InitializeComponent();            init();        }                    ///<summary>/// 初始化共享内存数据 创建一个共享内存        ///</summary>privatevoid init()        {            m_Write = new Semaphore(, , "WriteMap");//开始的时候有一个可以写            m_Read = new Semaphore(, , "ReadMap");//没有数据可读            mapLength = ;            IntPtr hFile = new IntPtr(INVALID_HANDLE_VALUE);            handle = CreateFileMapping(hFile, , PAGE_READWRITE, , mapLength, "shareMemory");            addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, , , );            //handle = OpenFileMapping(0x0002, 0, "shareMemory");            //addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);            threadRed = new Thread(new ThreadStart(ThreadReceive));            threadRed.Start();        }        /// <summary>        /// 线程启动从共享内存中获取数据信息         /// </summary>        private void ThreadReceive()        {            myDelegate myI = new myDelegate(changeTxt);            while (true)            {                try                {                    //m_Write = Semaphore.OpenExisting("WriteMap");                    //m_Read = Semaphore.OpenExisting("ReadMap");                    //handle = OpenFileMapping(FILE_MAP_WRITE, 0, "shareMemory");                    //读取共享内存中的数据:                    //是否有数据写过来                    m_Read.WaitOne();                    //IntPtr m_Sender = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);                    byte[] byteStr = new byte[];                    byteCopy(byteStr, addr);                    string str = Encoding.Default.GetString(byteStr, , byteStr.Length);                   /////调用数据处理方法 处理读取到的数据                    m_Write.Release();                }                catch (WaitHandleCannotBeOpenedException)                {                    continue;                    //Thread.Sleep(0);                }            }        }        //不安全的代码在项目生成的选项中选中允许不安全代码        static unsafe void byteCopy(byte[] dst, IntPtr src)        {            fixed (byte* pDst = dst)            {                byte* pdst = pDst;                byte* psrc = (byte*)src;                while ((*pdst++ = *psrc++) != '\0')                    ;            }        }    }}

B进程向共享内存中写入的数据

using System;

using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Runtime.InteropServices;using System.Threading;namespace AppTwo{    public partial class AppTwoMain : Form    {        const int INVALID_HANDLE_VALUE = -;        const int PAGE_READWRITE = 0x04;        //共享内存        [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")]        private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile,         UInt32 lpAttributes,//LPSECURITY_ATTRIBUTES lpAttributes,  //         UInt32 flProtect,//DWORD flProtect         UInt32 dwMaximumSizeHigh,//DWORD dwMaximumSizeHigh,         UInt32 dwMaximumSizeLow,//DWORD dwMaximumSizeLow,         string lpName//LPCTSTR lpName         );        [DllImport("Kernel32.dll", EntryPoint = "OpenFileMapping")]        private static extern IntPtr OpenFileMapping(         UInt32 dwDesiredAccess,//DWORD dwDesiredAccess,         int bInheritHandle,//BOOL bInheritHandle,         string lpName//LPCTSTR lpName         );        const int FILE_MAP_ALL_ACCESS = 0x0002;        const int FILE_MAP_WRITE = 0x0002;        [DllImport("Kernel32.dll", EntryPoint = "MapViewOfFile")]        private static extern IntPtr MapViewOfFile(         IntPtr hFileMappingObject,//HANDLE hFileMappingObject,         UInt32 dwDesiredAccess,//DWORD dwDesiredAccess         UInt32 dwFileOffsetHight,//DWORD dwFileOffsetHigh,         UInt32 dwFileOffsetLow,//DWORD dwFileOffsetLow,         UInt32 dwNumberOfBytesToMap//SIZE_T 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);        private Semaphore m_Write;  //可写的信号        private Semaphore m_Read;  //可读的信号        private IntPtr handle;     //文件句柄        private IntPtr addr;       //共享内存地址        uint mapLength;            //共享内存长        Thread threadRed;        public AppTwoMain()        {            InitializeComponent();            //threadRed = new Thread(new ThreadStart(init));            //threadRed.Start();            mapLength = ;                    }        private void button1_Click(object sender, EventArgs e)        {            try            {                m_Write = Semaphore.OpenExisting("WriteMap");                m_Read = Semaphore.OpenExisting("ReadMap");                handle = OpenFileMapping(FILE_MAP_WRITE, , "shareMemory");                addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, , , );                m_Write.WaitOne();                byte[] sendStr = Encoding.Default.GetBytes(textBox1.Text.ToString() + '\0');                //如果要是超长的话,应另外处理,最好是分配足够的内存                if (sendStr.Length < mapLength)                    Copy(sendStr, addr);                                m_Read.Release();                                            }            catch (WaitHandleCannotBeOpenedException)            {                MessageBox.Show("不存在系统信号量!");                return;            }        }        static unsafe void Copy(byte[] byteSrc, IntPtr dst)        {            fixed (byte* pSrc = byteSrc)            {                byte* pDst = (byte*)dst;                byte* psrc = pSrc;                for (int i = ; i < byteSrc.Length; i++)                {                    *pDst = *psrc;                    pDst++;                    psrc++;                }            }        }   }}

C# 进程间通信(共享内存)的更多相关文章

  1. Linux环境进程间通信: 共享内存

    Linux环境进程间通信: 共享内存 第一部分 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进 ...

  2. linux进程间通信-共享内存

    转载:http://www.cnblogs.com/fangshenghui/p/4039720.html 一 共享内存介绍 共享内存可以从字面上去理解,就把一片逻辑内存共享出来,让不同的进程去访问它 ...

  3. Linux下进程间通信--共享内存:最快的进程间通信方式

    共享内存: 一.概念: 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间. 进程A可以即时看到进程B ...

  4. Linux进程间通信—共享内存

    五.共享内存(shared memory) 共享内存映射为一段可以被其他进程访问的内存.该共享内存由一个进程所创建,然后其他进程可以挂载到该共享内存中.共享内存是最快的IPC机制,但由于linux本身 ...

  5. Windows进程间通信--共享内存映射文件(FileMapping)--VS2012下发送和接收

    之前以为两个互不相关的程序a.exe b.exe通信就只能通过网络,人家说可以通过发消息,我还深以为不然,对此,我表示万分惭愧. 之前课本上说的进程间通信,有共享内存.管道等之类的,但没有自己操刀写过 ...

  6. Linux 进程间通信 共享内存

    1.特点: 1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝.如管道当在内核空间创建以后,用户空间需要内存  拷贝,需要拷贝数据,所以效率低. 2)为了在多个进 ...

  7. linux 进程间通信 共享内存 shmat

    系统调用mmap()通过映射一个普通文件实现共享内存.系统V则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信.也就是说,每个共享内存区域对应特殊文件系统shm中的一个文件(这是通过shm ...

  8. linux 进程间通信 共享内存 mmap

    共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反 ...

  9. win32下进程间通信——共享内存

    一.引言     在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.WIN32 API提供了许多函数使我们能够方便高效的进行进程间的通讯,通过这些函数我们可以控制不同进程间的数据交换 ...

随机推荐

  1. Ubuntu 下配置Samba 实现Linux和windows之间文件共享

    一 Samba 的安装: sudo apt-get insall sambasudo apt-get install smbfs 二 在Ubuntu中创建共享目录: mkdir  /home/shar ...

  2. SecureCRT7.3和SecureFX7.3的MAC下破解

    破解脚本:http://files.cnblogs.com/files/jieyuefeng/SecureCRTFX_mac_crack.zip 破解方法: sudo perl ~/Downloads ...

  3. Android学习【Android内核编译流程和错误笔记】

    博客:http://blog.csdn.net/muyang_ren Ubuntu14.04 LTS(要求是64位长期支持版LTS) Jdk1.8 内核:android4.0 一:jdk 1.解压jd ...

  4. kettle_为子server创建carte服务

    原创作品.出自 "深蓝的blog" 博客,深蓝的blog:http://blog.csdn.net/huangyanlong/article/details/46876783 把k ...

  5. 现代的新语言--Swift初探

    新的语言 WWDC简短的介绍,新的语言Swift就问世了,尽管新语言的名字导致贴吧下歌手粉丝和开发人员们争抢地盘- -,只是雨燕就是这么来了. WWDC keynote里给Swift打上了非常多标签: ...

  6. Python的学习

    1.psutil的安装 [root@YQY-TIAN- ~]# wget https://pypi.python.org/packages/source/p/psutil/psutil-2.0.0.t ...

  7. window成员和document成员

    输出浏览器成员和DOM成员(以下为safari浏览器测试)(浏览器不同对象成员有差异) window成员 <script type="text/javascript"> ...

  8. ExifInterface 多媒体文件附加信息

    简介         ExifInterface类主要描述多媒体文件比如JPG格式图片的一些附加信息,包括拍摄时的光圈.快门.白平衡.ISO.焦距.日期时间等各种和拍摄条件以及相机品牌.型号.色彩编码 ...

  9. 获取scrollTop兼容各浏览器的方法,以及body和documentElement

    1.各浏览器下 scrollTop的差异 IE6/7/8: 对于没有doctype声明的页面里可以使用  document.body.scrollTop 来获取 scrollTop高度 : 对于有do ...

  10. playframework简单介绍

    官方网站: https://www.playframework.com/documentation/2.5.x/Home 简介 编辑 Play!是一个full-stack(全栈的)Java Web应用 ...