ZeroMQ介绍及如何交叉编译在嵌入式Linux下使用

什么是ZeroMQ?

ZeroMQ(也称为ØMQ或ZMQ)是一个高性能的异步消息库,用于在分布式或多线程应用程序中传递消息。它提供了套接字抽象,允许开发人员以简单的API设计复杂的消息模式。ZeroMQ的设计宗旨是为高吞吐量、低延迟的消息传递提供支持,适用于需要快速、可靠和可扩展的数据传输的场景。

ZeroMQ的主要特性

  • 高性能:ZeroMQ在内存管理和调度方面进行了优化,能够达到低延迟和高吞吐量的要求。
  • 跨平台:支持多种操作系统,包括Linux、Windows和OSX。
  • 多种消息模式:支持请求-应答、发布-订阅、推-拉等多种通信模式,灵活性高。
  • 异步I/O:基于事件驱动的模型,能够处理高并发的消息。
  • 轻量级:ZeroMQ的库相对较小,便于嵌入到各种应用程序和设备中。

在嵌入式Linux下使用ZeroMQ

在嵌入式Linux平台上使用ZeroMQ,首先需要交叉编译它的库,以下是详细步骤。

准备交叉编译工具链

首先,确保你有一个合适的交叉编译工具链。以下是一个示例的CMake工具链配置文件,假设目标架构为ARM。

创建一个名为 toolchain.cmake 的文件,内容如下:

# 交叉编译工具链配置文件

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

# 设置ARM工具链的路径
set(ARM_TOOLCHAIN_PREFIX "/path/to/your/toolchain/arm-linux-gnueabi")

set(CMAKE_C_COMPILER "${ARM_TOOLCHAIN_PREFIX}-gcc")
set(CMAKE_CXX_COMPILER "${ARM_TOOLCHAIN_PREFIX}-g++")
set(CMAKE_FIND_ROOT_PATH "/path/to/sysroot")

# 查找规则
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

请确保将工具链路径和sysroot路径替换为您自己的路径。

获取ZeroMQ源码

从ZeroMQ的GitHub仓库下载源码。您可以通过以下命令获取:

git clone https://github.com/zeromq/libzmq.git
## 如果是c++,则还需要使用下面这个:
git clone https://github.com/zeromq/cppzmq.git

交叉编译ZeroMQ

在下载的ZeroMQ源码目录下创建一个构建目录:

cd libzmq
mkdir build
cd build

然后使用CMake和之前创建的工具链文件进行配置:

cmake .. -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake -DCMAKE_INSTALL_PREFIX=/path/to/install
  • CMAKE_INSTALL_PREFIX:指定安装路径。

配置完成后,运行Make进行编译和安装:

make
make install

使用cppzmq

 https://github.com/zeromq/cppzmq 

cppzmq 是 libzmq 的 C++ 绑定库。其设计目标如下:

cppzmq 将 libzmq 的 C API 映射到 C++ 概念。具体来说:

  • 它是类型安全的(libzmq 的 C API 将各种类似于类的概念暴露为 void*)
  • 它提供基于异常的错误处理(libzmq 的 C API 提供基于 errno 的错误处理)
  • 它提供遵循 RAII 风格的类以自动化资源管理(libzmq 的 C API
    要求用户显式地释放资源)

cppzmq 是一个轻量级的、仅包含头文件的绑定库。您只需包含头文件 zmq.hpp(及可能的 zmq_addon.hpp)即可使用。
zmq.hpp 旨在包含 libzmq C API 提供的抽象的直接映射,而 zmq_addon.hpp 提供了额外的更高级别的抽象。

注意,使用这个库同样需要先安装上面的libzmq,比如上面的是安装在${HOME}/arm_install路径下。

如果使用cmake的方式使用则需要下面的操作:

#1. cd cppzmq,cd build
cd cppzmd
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=${HOME}/arm_install -DCPPZMQ_BUILD_TESTS=OFF -DZeroMQ_INCLUDE_DIR=${HOME}/arm_install/include/ -DZeroMQ_LIBRARY=${HOME}/arm_install/lib/
#2.
make
#3.安装
make install

在这里插入图片描述
在这里插入图片描述

在嵌入式Linux项目中使用ZeroMQ

在您的嵌入式Linux项目代码中,您可以通过包含ZeroMQ的头文件来使用它:

#include <zmq.hpp>
#include <iostream>

int main() {
    // 创建上下文
    zmq::context_t context(1);

    // 创建一个请求套接字
    zmq::socket_t socket(context, ZMQ_REQ);
    socket.connect("tcp://localhost:5555");

    // 发送消息
    zmq::message_t request(5);
    memcpy(request.data(), "Hello", 5);
    socket.send(request);

    // 接收回复
    zmq::message_t reply;
    socket.recv(&reply);
    std::cout << "Received: " << static_cast<char*>(reply.data()) << std::endl;

    return 0;
}

测试demo 的 CMakeLists.txt文件内容如下:

cmake_minimum_required(VERSION 3.5)
project(zmq_example)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 获取 ZeroMQ 库
find_package(cppzmq REQUIRED)


# 添加你的可执行文件
add_executable(zmq_example main.cpp)

# 链接 cppzmq 库
target_link_libraries(zmq_example cppzmq)

创建build文件夹,cd build, 然后执行以下指令:

cmake .. -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake -DTARGET_ARCH=arm 
#
make

在这里插入图片描述

在上述示例中,我们创建了一个ZeroMQ请求套接字,连接到指定的端口,发送了一条消息并接收了回复。

附:toolchain.cmake文件:
我的开发板环境: 正点原子 imx6ul开发板

# 交叉编译工具链配置文件
# 用于嵌入式Linux系统和RISC-V MCU的交叉编译

# 设置系统名称
set(CMAKE_SYSTEM_NAME Linux)

# 设置处理器架构变量,可以通过命令行参数传入
# 例如: cmake -DTARGET_ARCH=arm ..
if(NOT DEFINED TARGET_ARCH)
    set(TARGET_ARCH "arm" CACHE STRING "Target architecture (arm or riscv)")
endif()

# 设置ARM工具链路径
set(ARM_TOOLCHAIN_PATH "/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi")
# 设置RISC-V工具链路径
set(RISCV_TOOLCHAIN_PATH "/opt/tronlong/tina5.0_v1.0/rtos/lichee/rtos/tools/riscv64-elf-x86_64-20201104")

# 根据目标架构设置主工具链
if(${TARGET_ARCH} STREQUAL "arm")
    # ARM Linux工具链配置
    set(CMAKE_C_COMPILER ${ARM_TOOLCHAIN_PATH}/arm-poky-linux-gnueabi-gcc)
    set(CMAKE_CXX_COMPILER ${ARM_TOOLCHAIN_PATH}/arm-poky-linux-gnueabi-g++)
    set(CMAKE_FIND_ROOT_PATH /opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/)
    set(CMAKE_SYSTEM_PROCESSOR arm)
    
    # 设置额外的编译标志
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mfloat-abi=hard -mfpu=neon" CACHE STRING "" FORCE)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mfloat-abi=hard -mfpu=neon" CACHE STRING "" FORCE)
    
    # 设置链接器
    set(CMAKE_LINKER ${CMAKE_C_COMPILER})
    set(CMAKE_AR ${ARM_TOOLCHAIN_PATH}/arm-poky-linux-gnueabi-ar)
    set(CMAKE_RANLIB ${ARM_TOOLCHAIN_PATH}/arm-poky-linux-gnueabi-ranlib)
    
elseif(${TARGET_ARCH} STREQUAL "riscv")
    # RISC-V工具链配置 (C906核心)
    set(CMAKE_C_COMPILER ${RISCV_TOOLCHAIN_PATH}/bin/riscv64-unknown-elf-gcc)
    set(CMAKE_CXX_COMPILER ${RISCV_TOOLCHAIN_PATH}/bin/riscv64-unknown-elf-g++)
    set(CMAKE_FIND_ROOT_PATH ${RISCV_TOOLCHAIN_PATH}/riscv64-unknown-elf)
    set(CMAKE_SYSTEM_PROCESSOR riscv)
    
    # 设置RISC-V特定的编译标志 (C906核心)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=rv64gcv0p7 -mabi=lp64d" CACHE STRING "" FORCE)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=rv64gcv0p7 -mabi=lp64d" CACHE STRING "" FORCE)
    
    # 设置链接器
    set(CMAKE_LINKER ${CMAKE_C_COMPILER})
    set(CMAKE_AR ${RISCV_TOOLCHAIN_PATH}/bin/riscv64-unknown-elf-ar)
    set(CMAKE_RANLIB ${RISCV_TOOLCHAIN_PATH}/bin/riscv64-unknown-elf-ranlib)
    
else()
    message(FATAL_ERROR "不支持的目标架构: ${TARGET_ARCH}. 请使用 'arm' 或 'riscv'")
endif()

# 定义ARM工具链变量,供CMakeLists.txt使用
set(ARM_C_COMPILER ${ARM_TOOLCHAIN_PATH}/arm-linux-gnueabi-gcc)
set(ARM_CXX_COMPILER ${ARM_TOOLCHAIN_PATH}/arm-linux-gnueabi-g++)
set(ARM_AR ${ARM_TOOLCHAIN_PATH}/arm-linux-gnueabi-ar)
set(ARM_RANLIB ${ARM_TOOLCHAIN_PATH}/arm-linux-gnueabi-ranlib)
set(ARM_C_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon")
set(ARM_CXX_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon")

# 定义RISC-V工具链变量,供CMakeLists.txt使用
set(RISCV_C_COMPILER ${RISCV_TOOLCHAIN_PATH}/bin/riscv64-unknown-elf-gcc)
set(RISCV_CXX_COMPILER ${RISCV_TOOLCHAIN_PATH}/bin/riscv64-unknown-elf-g++)
set(RISCV_AR ${RISCV_TOOLCHAIN_PATH}/bin/riscv64-unknown-elf-ar)
set(RISCV_RANLIB ${RISCV_TOOLCHAIN_PATH}/bin/riscv64-unknown-elf-ranlib)
set(RISCV_C_FLAGS "-march=rv64gcv0p7 -mabi=lp64d")
set(RISCV_CXX_FLAGS "-march=rv64gcv0p7 -mabi=lp64d")

# 设置查找规则
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# 禁用系统库路径
set(CMAKE_SKIP_RPATH TRUE)

# 设置交叉编译环境的库和头文件搜索路径
set(CMAKE_SYSROOT ${CMAKE_FIND_ROOT_PATH}) 

# 关键!!!,不能漏掉这个设置
set(CMAKE_FIND_ROOT_PATH /root/arm_install)

总结

ZeroMQ是一个强大且灵活的消息传递库,适合多种场景,尤其是在嵌入式Linux系统中。通过交叉编译,您可以轻松将ZeroMQ集成到嵌入式项目中,为您的应用提供高性能的消息传递能力。希望本文对您在嵌入式环境中使用ZeroMQ有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

特立独行的猫a

您的鼓励是我的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值