开发者社区> 杰克.陈> 正文

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

简介: 原文:C# 进程间通信(共享内存) 进程间通信的方式有很多,常用的方式有: 1.共享内存(内存映射文件,共享内存DLL)。 2.命名管道和匿名管道。 3.发送消息  本文是记录共享内存的方式进行进程间通信,首先要建立一个进程间共享的内存地址,创建好共享内存地址后,一个进程向地址中写入数据,另外的进程从地址中读取数据。
+关注继续查看
原文: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 = -1;
        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,  //0
         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(11"WriteMap");//开始的时候有一个可以写
            m_Read = new Semaphore(01"ReadMap");//没有数据可读
            mapLength = 1024;
            IntPtr hFile = new IntPtr(INVALID_HANDLE_VALUE);
            handle = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, mapLength, "shareMemory");
            addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 000);

            //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[100];
                    byteCopy(byteStr, addr);
                    string str = Encoding.Default.GetString(byteStr, 0, 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 = -1;
        const int PAGE_READWRITE = 0x04;
        //共享内存
        [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")]
        private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile,
         UInt32 lpAttributes,//LPSECURITY_ATTRIBUTES lpAttributes,  //0
         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 = 1024;
            
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                m_Write = Semaphore.OpenExisting("WriteMap");
                m_Read = Semaphore.OpenExisting("ReadMap");
                handle = OpenFileMapping(FILE_MAP_WRITE, 0"shareMemory");
                addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 000);

                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 = 0; i < byteSrc.Length; i++)
                {
                    *pDst = *psrc;
                    pDst++;
                    psrc++;
                }
            }
        }

   }
}

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
进程间通信
有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变
60 0
【Linux】进程间通信 —— 匿名管道 | 命名管道 | System V | 共享内存
本文重点:进程间通信宏观认识;匿名管道;命名管道;共享内存;信号量(多线程)
293 0
Linux系统编程-进程间通信(共享内存)
共享内存也是进程间(进程间不需要有继承关系)通信的一种常用手段。一般OS通过内存映射与页交换技术,使进程的内存空间映射到不同的物理内存,这样能保证每个进程运行的独立性,不至于受其它进程的影响。但可以通过共享内存的方式,使不同进程的虚拟内存映射到同一块物理内存,一个进程往这块物理内存中更新的数据,另外的进程可以立即看到这块物理内存中修改的内容。
121 0
进程间通信——共享内存
进程间通信——共享内存
129 0
+关注
杰克.陈
一个安静的程序猿~
文章
问答
视频
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载