共享内存在不同进程中交互,共享内存名字相同可以访问

程序演示了如何使用共享内存传递JSON数据。
主要功能如下:
将JSON数据写入共享内存;
从共享内存中读取JSON数据并解析;
在不同的进程中读取共享内存中的数据。

利用rapidjson库生成一个JSON文档对象,然后将该JSON对象序列化为字符串,将其复制到共享内存中。通过信号量的方式告知读取进程可以开始读取数据。主进程将读取共享内存中的JSON字符串,然后将其解析为JSON对象,并打印出每个元素的键和值。

在main函数中,创建一个JSON文档对象,将该文档对象设置为一个JSON对象,并创建一个空数组。然后向数组中添加100个键值对。将数组添加到JSON对象中,利用shared_memory_json.WriteJsonToSharedMemory(document);函数将JSON对象写入共享内存中。然后,利用shared_memory_json.ReadJsonFromSharedMemory(data);函数从共享内存中读取JSON字符串,并解析JSON对象,打印出每个元素的键和值。

最后,创建一个子进程。在子进程中,利用shared_memory_json.ReadJsonFromSharedMemory(data);函数读取共享内存中的JSON字符串,并解析JSON对象,打印出每个元素的键和值。注意,子进程在父进程休眠2秒后才开始读取共享内存。

实现在不同进程中传递变长json;在ROS系统中与非ROS系统进行交互例子,或者相同环境下数据交互解析。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sys/mman.h>
#include <fcntl.h>
#include <semaphore.h>
#include <unistd.h>
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

using namespace rapidjson;

class SharedMemoryJSON {
public:
    SharedMemoryJSON() {}

    ~SharedMemoryJSON() {}

public:
    void WriteJsonToSharedMemory(const Document& document) {
        // 将JSON对象序列化为字符串
        StringBuffer buffer;
        Writer<StringBuffer> writer(buffer);
        document.Accept(writer);
        json_str_ = buffer.GetString();

        // 创建共享内存
        int shmid_ = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);

        if (shmid_ < 0) {
            perror("shmget");
            std::exit(EXIT_FAILURE);
        }
        // 设置共享内存大小
        ftruncate(shmid_, SHM_SIZE);
        // 将共享内存段附加到进程地址空间
        void* shm_ptr = mmap(nullptr, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shmid_, 0);
        // 创建信号量
        sem_t* sem = sem_open(SEM_NAME, O_CREAT, 0666, 0);
        if (sem == SEM_FAILED){
            std::cout << "Failed to create semaphore" << std::endl;
        }
        // 将JSON字符串复制到共享内存段
        std::memcpy(shm_ptr, json_str_.c_str(), strlen(json_str_.c_str()) + 1);

        // 发送信号量通知读取进程可以开始读取数据
        sem_post(sem);
    }

    void ReadJsonFromSharedMemory(char*& data1)
    {
        int shm_fd = shm_open(SHM_NAME, O_RDONLY, 0666);
        void* shm_ptr = mmap(nullptr, SHM_SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);

        // 从共享内存中读取数据
        char* data = static_cast<char*>(shm_ptr);
        data1 = data;
        std::cout << "Received data: " << data << std::endl;
    }

private:
    std::string json_str_;
    int shmid_;
    char* shmaddr_;
    static constexpr int SHM_SIZE = 4096;        // 共享内存大小
    const char* SHM_NAME = "/myshm";  // 共享内存名称
    const char* SEM_NAME = "/mysem";            // 信号量名称
};

int main() {
    Document document;  // 创建一个JSON文档对象
    document.SetObject();  // 将该文档对象设置为一个JSON对象
    Document::AllocatorType& allocator = document.GetAllocator();  // 获取分配器
    Value hobbies(kArrayType);  // 创建一个空数组

    // 向数组中添加100个键值对
    for (int i = 0; i < 100; ++i) {
        Value object(kObjectType);
        object.AddMember("key", i, allocator);
        object.AddMember("value", i * 2, allocator);
        hobbies.PushBack(object, allocator);
    }

    // 将数组添加到JSON对象中
    document.AddMember("hobbies", hobbies, allocator);
    SharedMemoryJSON shared_memory_json;
    shared_memory_json.WriteJsonToSharedMemory(document);


    std::cout<<"----------------------同一个进程读取--------------------------"<<std::endl;
    // 父进程执行的代码
    //----------------------read---------------------------同一个进程读取

    // 从共享内存打印JSON字符串
    char* data;
    shared_memory_json.ReadJsonFromSharedMemory(data);

    // 输出从共享内存读取的JSON字符串
    std::cout << "JSON string in shared memory: " << data << std::endl;


    // 读取JSON字符串并解析
    Document document1;
    document1.Parse(data);

    // 解析JSON对象并打印数组中每个元素的key和value值
    if (!document1.IsObject() || !document1.HasMember("hobbies") || !document1["hobbies"].IsArray()) {
        std::cerr << "Invalid JSON object." << std::endl;
        return 1;
    }

    const auto& hobbies1 = document1["hobbies"];
    for (const auto& object : hobbies1.GetArray())
    {
        if (!object.IsObject() || !object.HasMember("key") || !object.HasMember("value") || !object["key"].IsInt() || !object["value"].IsInt()) {
            std::cerr << "Invalid JSON object." << std::endl;
            return 1;
        }
        std::cout << "key: " << object["key"].GetInt() << ", value: " << object["value"].GetInt() << std::endl;
    }
    
    sleep(2);

    //----------------------解析--------------------------不同进程读取

    pid_t pid = fork();
    if (pid == -1)
    {
        std::cout << "Failed to create child process." << std::endl;
        return 1;
    }
    else if (pid == 0)
    {
        std::cout << "不同进程共享内存读取" << std::endl;
        // 子进程执行的代码
        std::cout << "Child process with PID " << getpid() << " started." << std::endl;

        const char* SEM_NAME = "/mysem";  // 信号量名称
        const char* SHM_NAME = "/myshm";
        int SHM_SIZE = 4096;        // 共享内存大小

        int shm_fd = shm_open(SHM_NAME, O_RDONLY, 0666);

        if (shm_fd == -1) {
            std::cout << "Failed to open shared memory" << std::endl;
            return -1;
        }
        void *shm_ptr01 = mmap(nullptr, SHM_SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);

        sem_t *sem = sem_open(SEM_NAME, O_CREAT, 0666, 0);
        if (sem == SEM_FAILED) {
            std::cout << "Failedto create semaphore" << std::endl;
            return -1;
        }
        // 等待写入进程写入数据
        sem_wait(sem);

        // 从共享内存中读取数据
        char *data2 = (char *) shm_ptr01;
        std::cout << "Received data: " << data2 << std::endl;

    }
    



    return 0;
}

```bash
cmake_minimum_required(VERSION 3.16)
project(JSON_parsing_shared_memory)

set(CMAKE_CXX_STANDARD 14)

add_executable(JSON_parsing_shared_memory main.cpp)
target_link_libraries(JSON_parsing_shared_memory rt)
target_link_libraries(JSON_parsing_shared_memory pthread)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

起个网名真难~

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值