windows进程通信之共享内存那点事

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

第一次做服务程序,碰到不少问题,稍作总结,留作后用。

 

程序结构

一个服务程序(A),每当有新用户登录,启动一个托盘(B),服务程序可以发数据给托盘,托盘也可以发数据给服务程序。因为二者都是在本机由此想到了使用共享内存。

新建两块共享内存,一块用作A写B读,另一块B写A读。因为server操作系统支持多用户登录,所以可能存在多个B程序。

 

A的大概代码:

//关于填充子进程命令行参数要多说一句,B写好数据之后要通知A来读,所以要发送一个消息给A,此时调用PostThreadMessage,第一个参数便是目的地的主线程ID

char szCmdLine[MAX_PATH];
sprintf_s(szCmdLine, MAX_PATH, "%ld",oGlobalConfig.dwMainThreadId

LPTSTR szCmdline = _tcsdup((LPCTSTR)szCmdLine);

//创建子进程,创建之后要保留子进程的主线程ID,从pi取得。这个也是A写完数据后发消息给B,通知B来读取共享内存的数据

if (!CreateProcessAsUser( pExplorerToken[i] ,strTrayName.c_str(), szCmdLine ,
      NULL,NULL,FALSE , NORMAL_PRIORITY_CLASS| CREATE_NEW_CONSOLE ,NULL,NULL,&si,&pi ) )
     {
      printf("打开失败 %s\n",strTrayName.c_str());
     }

 //写完数据后通知B来取数据

bool WriteToShareMem(char *pTactics)
{
 if (!hShareMem || !pShareMem || !pTactics)
  return false;
 //写入共享区
 LPSEND_HEAD lpSendHead = (LPSEND_HEAD)pTactics;
 memcpy(pShareMem, pTactics, lpSendHead->PacketLength);
 //对vecChildThread加锁,因为当托盘程序退出时,需要从列表中清除对应ID
 EnterCriticalSection(&oGlobalConfig.cs_ChildThread);
 //写完后给托盘发送消息,托盘开始读数据
 if (0 == oGlobalConfig.vecChildThread.size())
 {
  LeaveCriticalSection(&oGlobalConfig.cs_ChildThread);
  return true;
 }

//此向量里保存的全是子进程的主线程ID
 vector<DWORD>::iterator iter = oGlobalConfig.vecChildThread.begin();
 for (; iter != oGlobalConfig.vecChildThread.end(); ++iter)
 {
  BOOL bRet = PostThreadMessage(*iter, WM_TRAYGETDATA, 0, 0);
 }
 LeaveCriticalSection(&oGlobalConfig.cs_ChildThread);
 return true;
}

 

至此,写数据完成,接下来是读取B写入的数据。这里用一个消息循环,来接收B发送的消息。这个消息循环一定要写在自winthread的主线程中,详见msdn

void AnalysisMsg()
{
 MSG msg;
 char *pMonitorData = NULL;//接收托盘发送的数据
 while (GetMessage(&msg, NULL, WM_USER, WM_USER+3))
 {
  if (msg.message == WM_MONITORGETDATA)//自定义消息
  {
   //读取共享内存数据

   pMonitorShare = (char *)MapViewOfFile(hMonitorShare, FILE_MAP_ALL_ACCESS, 0, 0, MONITOR_SHARE_SIZE);
   if (NULL == pMonitorShare)
   {
    continue;
   }
   else
   {
    LPSEND_HEAD lpHead = (LPSEND_HEAD)pMonitorShare;
    //判断操作类型

    switch (lpHead->TransactionNumber)
    {
    case TRAY_APP_UDISK_REGISTER:
     {

     数据处理

     }
     break;
    case TRAY_APP_UDISK_TACTICS:
     {
      数据处理

     }
     break;
    }
   }
  }
 }
}

 

B程序从命令行参数获取父进程的主线程ID

//通过命令行获取父进程的主线程ID
 LPSTR lpstr = GetCommandLine();
 string cmdline = lpstr;
 m_uiParentThreadId = DWORD(atol(cmdline.c_str()));

其他与A程序相差不多,只是创建共享内存之类的改为open即可。有一点要注意,假如加入同步互斥控制,则需要用到EVENT或MUTEX之类,服务程序中创建的这些内核对象,在子进程中打开时会提示“拒绝访问”,错误代号:5。因为服务程序的安全级别较高,所以在创建的时候要传入第一个参数,而不是NULL。假如是用NULL创建的,在子进程也可以访问,只是在open中的第一个参数传入SYNCHRONIZE即可,但这时候获得的句柄不能对其做重置操作,例如:ResetEvent。此时如果有需求,还是在创建时传入安全属性,因我没这种需求,所以暂时没去研究这个安全属性怎样设置。

 

总结:

1、有名内核对象如果在服务程序中创建,则要注意安全属性

2、共享内存时,用消息通知的方式通知对方来读数据。读写要进行加锁操作,我用的是mutex

 

命名管道通信和共享内存通信 介绍共享内存通讯和命名管道通讯两种通讯方式,包括命名管道的实现方式以及共享内存的思路。 阅读详情

相关推荐

【并发编程四】windows进程通信和Linux进程通信

原本写完上一篇[【并发编程三】C++进程通信(管道pipe)],就准备写消息队列的c++demo了,但是真正查找资料才发现网上都是linux下的消息队列的c++demo,就没有windows下的消息队列的进程通信的demwindows没有信号这个概念,但是会提供类似功能的api,比如,杀死进程:linux下的kill信号,windows下提供TerminateProcess的api接口。

junxuezheng的博客 2544

【学习笔记】windows 下的 shared memory(共享内存)原理与实践

共享内存是一种进程间的通信机制(其他的通信机制还有管道,消息队列等)。进程之间通过访问一块共享的空间,来进行数据的通信(交换)。具体来讲,就是将一份物理内存映射到不同进程各自的虚拟地址空间,这样每个进程都可以读写这片物理内存。共享内存是速度最快的一种进程间通信(IPC)方式,它直接对内存进行存取,比操作系统提供的读写系统服务更快。由上面的描述我们发现,当多个进程对同一片空间进行读写时必然会出现同步的问题,所以一般共享内存会和信号量或者锁机制一同使用,保证数据的完整性。

码的世界 1万+

Windows共享内存与死锁

总的来说这个实验还是很难的,花费了很长时间,也遇到了很多问题。首先为什么要映射,这其实是操作系统内存管理的知识,MapViewOfFile就是为了将此内存空间映射到进程的地址空间中。如果两个进程使用相同的DLL,只把DLL的代码页装入内存一次,其他所有映射这个DLL的进程只要共享这些代码页就可以了,如果利用消息机制实现IPC有交换的数据量小、携带的信息少等缺

Fishermen_sail的博客 1614

互相独立进程间共享内存互斥访问的解决办法

前提:两个进程互相独立,访问同一片共享内存存在问题:1、如何避免两个进程同时访问共享内存(一旦两个进程同时访问一个临界区,后果是程序崩溃)2、如果使用互斥锁,如何让两个进程拿到同一个互斥锁解决办法:针对问题1,可以使用信号,信号量,互斥锁来进行同步,但是信号和信号量需要两个进程都实现一套自己的逻辑(访问临界区前,先检查冲突标志,如果没有冲突则访问,并向其它的所有进程依次发送信号,告诉它们我要开始访...

每天进步一点点,月薪三千不是梦 1万+

进程间共享内存同步的三种方式

    如果我们有多个进程访问一块共享内存,有时候我们为了保证数据的一致我们不得不对共享内存中的数据采取同步措施。对于共享内存的同步基本上有以下三种方式。    一 记录锁(文件锁)       我们首先来看记录锁,记录锁的功能是当一个进程正在读或者修改文件的某一个部分时,它可以阻止其他进程修改同一文件区。它其实是“字节范围锁”,因为它锁定的是文件中的一个区域,当然,也可能是整个文件。   ...

D_Guco的专栏 1万+

共享内存进程间应用

在新的C++标准下,提供了很多新的锁,比如scoped_lock、shared_lock(对应的互斥体: timed_mutex、recursive_mutex、recursive_timed_mutex、shared_mutex、shared_timed_mutex)。还是要好好的看一看相关的锁的应用和跨进程中的使用的问题,没有实践就没有发言权。

fpcc的专栏 438

Windows进程通信共享内存通信

本文章先介绍共享内存是啥,再介绍使用共享内存要涉及的4个函数,最后将实例代码附上,实例代码用于加深理解,读者也可以模仿用例改编使用。 1. 共享内存的简单介绍 共享内存就是允许两个不相关的进程访问同一个虚拟内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都...

Quellaaa的博客 2089

qt共享内存

一、说明 查看此文,共享内存,相信大家都知道进程间通信,即IPC(Inter-Process Communication),进程间通信是指两个进程的数据之间产生交互。而共享内存是实现进程通信的方式之一,其他通信方式可看下图: 查看各通信方式优缺可访问链接,上图内容来源:进程间通讯的7种方式 应用场景分析 首先讨论一下为什么需要进程间通信?因为产品经理说项目需要。。。。。。,技术角度来说,不同的进程有自己的内存空间,正常情况下A进程是不能访问B进程的内存空间的。可是一些大型项目,因为项目业务比较复杂,于是

weixin_42887343的博客 7028

[进程通信] 管道 vs 共享内存 vs 网络

linux下一切皆文件

No Game No Life 1612

进程通信共享内存Windows

进程通信就是**不同进程之间互相传递数据和消息**,让它们能协同工作。我们这次重共享内存通信,直接在内存中开辟共享区域供多个进程访问。

m0_62297377的博客 1186

Windows系统——进程通信共享内存

Windows系统——进程通信共享内存区 实现代码 writer.cpp /* author : eclipse email : eclipsecs@qq.com time : Sun Apr 26 12:44:13 2020 */ #include<bits/stdc++.h> #include<conio.h> #include<windows.h&gt...

qq_44486439的博客 663

进程通信共享内存

共享内存就是允许两个不相关的进程访问同⼀个逻辑内存。共享内存是在两个正在运⾏的进程之间共享和传递数据的⼀种⾮常有效的⽅式。采⽤共享内存的通信效率⽐较⾼。优:因为所有进程共享同⼀块内存,所以共享内存在各种进程间通讯⽅式中具有最⾼的效率,因为进程可以直接读写内存,⽽不需要任何数据的拷⻉。缺:因为所有进程共享内存,就会引起同步的问题,⽽系统对访问共享内存没有进⾏同步机制,就需要⽤户⾃⼰来提供同步措施。IPCS命令简介。

hsjkdhs的博客 1194

Windows进程通信共享内存

共享内存主要是通过映射机制实现的。   Windows 下进程的地址空间在逻辑上是相互隔离的,但在物理上却是重叠的。所谓的重叠是指同一块内存区域可能被多个进程同时使用。系统把同一块内存区域映射到了不同进程的地址空间中,从而达到共享内存的目的。   示例代码中,一方是QT编写的程序来创建并读取共享内存的内容,另一方是VC程序修改共享内存中的内容:   QT: #include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> #

Flywithdawn的博客 1617

Windows共享内存详解

主要讲解了windows平台进程间共享数据的一种方法:共享内存

余识- 8279

Windows进程通信共享内存通信(C++)

首先是概念:https://baike.baidu.com/item/%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98/2182364?fr=aladdin 这是比较官方的解释 在我的理解,共享内存通信指的是,一个进程开辟一块内存,并且设定内存的读取方式,并且存放数据,然后另一个进程通过一个特定的key值来访问,并且读取里面的值。 接下来是我做的一个简单的客户端和服务...

MusicMan 2888

RTX与Windows进程通信实例

RTX与Windows进程通信实例 去发现同类优质开源项目:https://gitcode.com/ 此仓库提供了一个关于RTX与Windows进程通信的实例,主要包括以下两部分内容: 一个基于Windows MFC的程序,用于创建共享内存,并实现对其读写操作。 RTX进程通过读取共享内存来完成与Windows进程的通信。 开发环境:MS VS2005。 参考资料:RTX Help文档。 推荐...

gitblog_06704的博客 398

Windows系统编程(五)进程通信

进程是操作系统分配资源和调度的独立单位,由进程内核对象和进程内存地址空间构成。不同的进程内存地址空间相互隔离,因此一个进程无法直接访问另一个进程的内存数据。当进程间需要数据共享或任务协作时,就必须使用进程通信进程通信是指在不同进程之间的数据传输。简单的说进程通信就是多进程共享一份内存空间。接下来我们讲解几种不同方式的进程通信

2301_78838647的博客 689
上一篇: windows进程通信之共享内存那点事
下一篇: 由int与unsigned int 相加看c++类型转换
delete635
博客等级 码龄18年 2粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值