首页 程序笔记 C++使用boost实现进程间通讯:消息队列,共享内存,信号

C++使用boost实现进程间通讯:消息队列,共享内存,信号

前言

进程间通信(IPC)必然是C++程序员必掌握技能之一,而boost库是众多库中平台支持性很好,效果很高之一。做嵌入式或者服务器等应用的人肯定有所涉及。本文列举几种使用boost的常用IPC:共享内存,信号,以及消息队列的编程方式,供大家参考。

信号通信

信号是进程内通信,非常类似于Qt的信号槽,配合消息队列以及boost多线程使用效果很好,贴出一个常用带参数的写法,详细的其他用法可以参考文章末的参考文章:

#include boost/signal.hpp 
#include boost/thread/thread.hpp 
#include boost/date_time/posix_time/posix_time.hpp 
#include iostream 
 
using namespace std; 
using namespace boost; 
 
float print_sum(float x, float y) 
{ 
  std::cout  The sum is   x+y  std::endl; 
  return x+y; 
}
  
float print_product(float x, float y) 
{ 
  std::cout  The product is   x*y  std::endl; 
  return x*y; 
}
 
float print_difference(float x, float y) 
{ 
  std::cout  The difference is   x-y  std::endl; 
  return x-y; 
}
 
float print_quotient(float x, float y) 
{
   std::cout  The quotient is   x/y  std::endl; 
  return x/y; 
}
 
int main() 
{
  boost::signalfloat (float , float ) sig; 
  sig.connect(0, print_sum); 
  sig.connect(1, print_product); 
  sig.connect(2, print_difference); 
  sig.connect(3, print_quotient); 
  // Output 1.6667 because return by the last slot called. 
  cout  sig(5, 3)  endl;    
  return 0; 
}

信号槽删除及阻塞

Seg 1: Disconnecting slots.
 
        boost::signals::connection c = sig.connect(HelloWorld());
 
        if (c.connected()) {
 
        // c is still connected to the signal
 
        sig(); // Prints Hello, World!
 
        }
 
        c.disconnect(); // Disconnect the HelloWorld object
 
        assert(!c.connected()); //c isnt connected any more
 
        sig(); // Does nothing: there are no connected slots
 
Seg 2:
 
        boost::signals::connection c = sig.connect(HelloWorld());
 
        sig(); // Prints Hello, World!
 
 
 
        c.block(); // block the slot
 
        assert(c.blocked());
 
        sig(); // No output: the slot is blocked
 
 
 
        c.unblock(); // unblock the slot
 
        sig(); // Prints Hello, World!

共享内存

#include boost/interprocess/shared_memory_object.hpp  
#include boost/interprocess/mapped_region.hpp  
#include cstring  
#include cstdlib  
#include string  
   
int main(int argc, char *argv[])  
{  
   using namespace boost::interprocess;  
   
   if(argc == 1){  //Parent process  
      //Remove shared memory on construction and destruction  
      struct shm_remove  
      {  
         shm_remove() { shared_memory_object::remove(MySharedMemory); }  
         ~shm_remove(){ shared_memory_object::remove(MySharedMemory); }  
      } remover;  
   
      //Create a shared memory object.  
      shared_memory_object shm (create_only, MySharedMemory, read_write);  
   
      //Set size  
      shm.truncate(1000);  
   
      //Map the whole shared memory in this process  
      mapped_region region(shm, read_write);  
   
      //Write all the memory to 1  
      std::memset(region.get_address(), 1, region.get_size());  
   
      //Launch child process  
      std::string s(argv[0]); s +=  child ;  
      if(0 != std::system(s.c_str()))  
         return 1;  
   }  
   else{  
      //Open already created shared memory object.  
      shared_memory_object shm (open_only, MySharedMemory, read_only);  
   
      //Map the whole shared memory in this process  
      mapped_region region(shm, read_only);  
   
      //Check that memory was initialized to 1  
      char *mem = static_castchar*(region.get_address());  
      for(std::size_t i = 0; i  region.get_size(); ++i)  
         if(*mem++ != 1)  
            return 1;   //Error checking memory  
   }  
   return 0;  
} 

消息队列

消息队列发送:

#include boost/interprocess/ipc/message_queue.hpp
#include iostream
#include vector
 
using namespace boost::interprocess;
 
int main ()
{
   try{
      //Erase previous message queue
      message_queue::remove(message_queue);
 
      //Create a message_queue.
      message_queue mq
         (create_only               //only create
         ,message_queue           //name
         ,100                       //max message number
         ,sizeof(int)               //max message size
         );
 
      //Send 100 numbers
      for(int i = 0; i  100; ++i){
         mq.send(i, sizeof(i), 0);
      }
 
 
   }
   catch(interprocess_exception ex){
      std::cout  ex.what()  std::endl;
      return 1;
   }
 
   return 0;
}

消息队列接收:

#include boost/interprocess/ipc/message_queue.hpp
#include iostream
#include vector
 
using namespace boost::interprocess;
 
int main ()
{
   try{
      //Open a message queue.
      message_queue mq
         (open_only        //only create
         ,message_queue  //name
         );
 
      unsigned int priority;
      message_queue::size_type recvd_size;
 
      //Receive 100 numbers
      for(int i = 0; i  100; ++i)
	  {
         int number;
         mq.receive(number, sizeof(number), recvd_size, priority);
		 printf(I:%d Rec:%d\n,i,number);
         if(number != i || recvd_size != sizeof(number))
            return 1;
      }
   }
   catch(interprocess_exception ex){
      message_queue::remove(message_queue);
      std::cout  ex.what()  std::endl;
      return 1;
   }
   message_queue::remove(message_queue);
   return 0;
}

消息队列封装

将消息队列整理了一下,可以直接方便使用如下:
注(BoostMsg.h)用于将函数外部化,无其他用处。

#include BoostMsg.h
 
#include boost/interprocess/ipc/message_queue.hpp  
#include iostream  
#include vector  
 
using namespace boost::interprocess;  
 
int BoostMsg_CreateMsg(const char* MsgQueName,int MaxQueLen,int MaxMsgLen)
{
	message_queue::remove(MsgQueName);  
	//Create a message_queue.  
	message_queue mq  
		(create_only               //only create  
		,MsgQueName						//name  
		,MaxQueLen                       //max message number  
		,MaxMsgLen              //max message size  
		);  
 
	printf(Boost Msg Created Name:%s QueLen:%d MsgMaxLen:%d \n,MsgQueName,MaxQueLen,MaxMsgLen);
 
	return 0;
}
 
int BoostMsg_OpenMsgToSend(char* BufMsg,const char* MsgQueName,int MsgLen)
{  
	try{  
		//Erase previous message queue  
		//message_queue::remove(message_queue);  
		//Create a message_queue.  
		message_queue mq  
			(open_only               //only create  
			,MsgQueName						//name  
			);  
 
		mq.send(BufMsg, MsgLen, 0);  
	}  
	catch(interprocess_exception ex){  
		std::cout  ex.what()  std::endl;  
		return 1;  
	}  
	return 0;  
} 
 
 
 
int BoostMsg_OpenMsgToRec(char* RecivedMsg,const char* MsgQueName,int MaxReceivedLen)
{  
	try{  
		//Open a message queue.  
		message_queue mq  
			(open_only        //only create  
			,MsgQueName  //name  
			);  
 
		unsigned int priority;  
		message_queue::size_type recvd_size;  
 
		memset(RecivedMsg,0,MaxReceivedLen);
		mq.receive(RecivedMsg, MaxReceivedLen, recvd_size, priority);  
		return recvd_size;
 
	}  
	catch(interprocess_exception ex){  
		message_queue::remove(message_queue);  
		std::cout  ex.what()  std::endl;  
		return 1;  
	}  
	message_queue::remove(message_queue);  
	return 0;  
}  

使用方法很简单,就是Create 然后Send 和Rec,进程之间通信 很方便。

编译命令:

[root@localhost tmp]# g++ boost_queue_send.cpp -o queue_send -lboost_thread -lboost_system
[root@localhost tmp]# g++ boost_queue_rec.cpp -o queue_rec -lboost_thread -lboost_system

参考文章

Boost.Interprocess使用手册翻译之四:在进程间共享内存 (Sharing memory between processes)
http://blog.csdn.net/great3779/article/details/7226388

Windows多进程编程
http://blog.csdn.net/bxhj3014/article/details/2082255

如何使用BOOST信号(一)
http://blog.csdn.net/liuchangyu23/article/details/4584045

Boost.Interprocess 强大的进程间通讯库
http://blog.csdn.net/linkerlin/article/details/2249906

如何使用BOOST信号(二)
http://blog.csdn.net/liuchangyu23/article/details/4584346

3

站心网

前言 进程间通信(IPC)必然是C++程序员必掌握技能之一,而boost库是众多库中平台支持性很好,效果很高之一..

为您推荐

使用 html2canvas 实现截图功能

html2canvas 是一个开源的 JavaScript 库,用于将网页上的 HTML 元素渲染成图像。它通过遍历页面的 DOM 树和计算样式,然后将其绘制到 <canvas> 元素上,最终生成图片。该库不依赖服务器端,而是通过浏览器端的 Java..

网站统计中的访问信息收集的前端实现

网站数据统计分析工具是网站站长和运营人员经常使用的一种工具,比较常用的有谷歌分析、百度统计和腾讯分析等等。所有这些统计分析工具的第一步都是网站访问数据的收集。目前主流的数据收集方式基本都是基于javascri..

使用SuperWebSocket实现Web消息推送

在大部分Web系统中,我们可能遇到需要向客户端推送消息的需求。SuperWebSocket第三方库能让我们轻松的完成任务。SuperWebSocket第三方库可以从网上下载,不过通过Visual Studio Nuget安装更快。引用SuperWebSocket相..

.NET C# 使用Hook钩子实现全局监听键盘和鼠标

C# 是一种面向对象的编程语言,具有丰富的类库和工具支持,适用于各种类型的应用程序开发。Windows 提供了一种称为"钩子"(Hook)的机制,允许拦截并处理系统级别的事件,如键盘按键和鼠标移动。通过结合 C# 和 Hook..

.NET C#连接FTP实现文件上传下载

在 .NET 中可以使用 System.Net.FtpWebRequest 类来连接 FTP 服务器,实现文件上传和下载。以下是实现文件上传和下载的完整代码示例。1. 上传文件到 FTP 服务器using System;using System.IO;using System.Net;class..

C#使用 Attribute 实现 AOP 功能

在 C# 中,通过自定义 Attribute 并结合一些技术(如动态代理、反射等)可以实现 AOP(面向切面编程)。AOP 通常用于日志记录、性能监控、权限验证等横切关注点。以下是一个使用 C# Attribute 实现 AOP 功能的示例。..

ABP.Net Core使用教程(一)启动模版项目

只需要简单的3步:1,到官网下载模版项目 https://aspnetboilerplate.com/Templates2,用VS2017打开,将Web.Host设置为启动项3,在程序包管理器控制台(Nuget控制台)里设定默认项目为EntityFrameworkCore,执行命令..

C#中的线程安全的集合ConcurrentQueue使用示例

在多线程编程中,如何安全地在不同线程之间共享数据是一个非常重要的问题。C# 为我们提供了一些专门设计的线程安全集合,其中之一就是 ConcurrentQueue<T>。它是一种先进先出(FIFO)的数据结构,专门为多线程环境设..

CSS砌体布局示例和使用场景

CSS砌体布局(Masonry Layout)CSS砌体布局是一种网页布局技术,它的灵感来源于砖石墙的排列方式,类似于“拼图”或“拼砖”的效果。在砌体布局中,元素的排列并不完全遵循传统的网格布局规则,..

使用CSS columns-visibility实现砌体布局

CSS的 columns 属性(如 columns、column-count 和 column-width)通常用于多列文本布局,而不是直接用于砌体布局。然而,结合 columns 和 visibility 属性,可以在某些情况下实现类似砌体布局的效果,虽然它并不完..

使用System.Linq.Dynamic.Core扩展库动态构建 LINQ 查询

System.Linq.Dynamic.Core 是一个扩展库,用于在运行时动态构建 LINQ 查询,支持字符串形式的表达式解析和动态查询操作。它是 .NET 的一个强大工具,适合处理需要灵活定义查询逻辑的场景,例如动态过滤、排序、投影..

小米开源智能家居平台 ha_xiaomi_home 使用示例

小米近期在 GitHub 上开源了名为“ha_xiaomi_home”的项目,即 Home Assistant 米家集成组件。该组件由小米官方支持,旨在让用户在 Home Assistant 中集成和控制小米 IoT 智能设备。主要特点:官方支持:..

C#13新特性 使用System.Threading.Lock简化线程同步

C# 13 引入了新的线程同步类型 System.Threading.Lock,它通过作用域管理的方式简化了锁的使用,使代码更加清晰可靠。本文将全面介绍 System.Threading.Lock 的功能、适用场景,并提供完整的运行示例程序。1. 什么是..

微软官方Microsoft.Extensions.AI库使用示例

Microsoft.Extensions.AI 库介绍Microsoft.Extensions.AI 是一个扩展库,用于在 .NET 应用程序中轻松集成人工智能(AI)服务,例如 OpenAI、Azure OpenAI 和其他支持文本生成或语言模型的 API。通过与 Microsoft.Ext..

.Net Core中Dapper的使用详解

1.安装Dapper这里直接使用Nuget安装。安装版本是1.50.5安装完成之后,发现Nuget下已经有了Dapper。2.创建DapperHelper接下来创建一个DapperHelper帮助类,来进行读取数据库连接字符串,打开数据库等操作。public cla..

最新CentOS7安装搭建shadowsocks服务端+客户端使用图文教程

使用的CentOS版本是7.9,其他版本也可以。超级推荐的是搭建shadowsocks服务端,安装配置都很简单,几分钟就搞定,客户端支持PC移动端,下面是安装shadowsocks的过程,只要复制粘贴命令就行了,文件夹路径都不需要改..

ASP.NET 使用Entity Framework (EF) 创建迁移修改SQLite数据库表结构

在 ASP.NET 中,使用 Entity Framework (EF) 创建并连接 SQLite 数据库是一种轻量级、高效的数据库管理方式。以下是详细步骤:安装必要的 NuGet 包安装EntityFrameworkCore.Sqlite包:Install-Package Microsoft.Ent..

使用shields.io来实时显示GitHub项目star、watch和fork的数量

如何获取GitHub repo实时的star,watch和fork数量呢?这里推荐一个Shields.io工具,可以实时生成GitHub徽章,同时显示star数。显示效果如下:什么是 Shields.io?Shields.io 是一个开源项目,用于生成各种类型的徽章..

.NET 开源 ORM FreeSql 使用教程

什么是 FreeSql?FreeSql 是一个高性能、灵活且易用的 .NET 开源 ORM(对象关系映射工具),提供数据库操作的强大功能,包括实体类映射、链式查询、表达式树支持、数据库迁移等。它可以帮助开发者快速、高效地操作数..

SQL Server EF使用Sequence全局自增ID

在使用 Entity Framework (EF) 时,如果需要在 SQL Server 中实现一个 全局自增 ID,可以通过以下方法来实现。全局自增 ID 的需求通常是为了在多表之间实现唯一性递增 ID。实现方式 1:使用 SQL Server 的 SequenceS..

发表回复

返回顶部