程序演示了如何使用共享内存传递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)