原文: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. cf435A Queue on Bus Stop

      A. Queue on Bus Stop time limit per test 1 second memory limit per test 256 megabytes input standa ...

  2. 扒一扒ReentrantLock以及AQS实现原理

    提到JAVA加锁,我们通常会想到synchronized关键字或者是Java Concurrent Util(后面简称JCU)包下面的Lock,今天就来扒一扒Lock是如何实现的,比如我们可以先提出一 ...

  3. thinkphp+datatables+ajax 大量数据服务器端查询

    今天一白天全耗在这个问题上了,知乎2小时除外... 现在19:28分,记下来以备后查. 问题描述:从后台数据库查询人员信息,1w多条,使用一个好看的基于bootstrap的模板 Bootstrap-A ...

  4. spring整合springMVC、mybatis、hibernate、mongodb框架

    开发环境 eclipse Mars 4.5 JDK 1.7 框架 spring 4.0.5 mybatis 3.2.7 hibernate 4.3.6 mongodb 1.7 数据库 MySQL 5. ...

  5. lesson6:jmeter和badboy配合使用

    由于jmeter不支持脚本的录制,只能手动设置,在某些集成型的压力测试时,使用不是很方便,这时可以和badboy一起配合使用,badboy支持网页操作的录制功能,并能把录制的操作导出为jmeter的脚 ...

  6. jquery easyui Tab 引入页面的问题

    jQuery Easyui 的tabs插件有两种方式加载某个tab(标签页)上的内容:“href远程请求”和“content本地内容”,本文就两种方式的优缺点进行简单分析和思考. 两者特点: href ...

  7. acid数据库事务正确执行的四个基本要素的缩写编辑本义项

    ACID,指数据库事务正确执行的四个基本要素的缩写.包含:原子性(Atomicity).一致性(Consistency).隔离性(Isolation).持久性(Durability).一个支持事务(T ...

  8. 基于mapreducer的图算法

    作者现就职阿里巴巴集团1688技术部 引言 周末看到一篇不错的文章"Graph Twiddling in a MapReduce world" ,介绍MapReduce下一些图算法 ...

  9. BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)

    题目大意:有一些位置.这些位置上能够放若干个数字. 如今有两种操作. 1.在区间l到r上加入一个数字x 2.求出l到r上的第k大的数字是什么 思路:这样的题一看就是树套树,关键是怎么套,怎么写.(话说 ...

  10. android 绘图

    在main.xml文件中代码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout ...