运行环境:ubuntu 20.4
进程间共享内存通信,通过信号量实现进程同步。
创建writer进程,reader进程,writer会每隔一段时间向共享内存写入新的数据,而reader会阻塞地等待并读取这些数据。
上代码:
// writer.cpp 文件
# writer.py
import time
import mmap
import posix_ipc
SHARED_MEMORY_NAME = "my_shared_memory"
SEM_WRITE_NAME = "sem_write"
SEM_READ_NAME = "sem_read"
MEMORY_SIZE = 1024
DATA = "Data from Python: {}"
# 创建信号量
sem_write = posix_ipc.Semaphore(SEM_WRITE_NAME, posix_ipc.O_CREAT, initial_value=1)
sem_read = posix_ipc.Semaphore(SEM_READ_NAME, posix_ipc.O_CREAT, initial_value=0)
# 创建共享内存
memory = posix_ipc.SharedMemory(SHARED_MEMORY_NAME, posix_ipc.O_CREAT, size=MEMORY_SIZE)
mapfile = mmap.mmap(memory.fd, MEMORY_SIZE)
memory.close_fd()
points = []
point = [111.34,222.33,555.78]
point = [str(item) for item in point]
try:
while True:
sem_write.acquire() # 等待获取写权限
point_str = ",".join(point) + ";"
print(point_str)
message = point_str.encode()
mapfile.seek(0)
mapfile.write(message.ljust(MEMORY_SIZE, b'\x00')) # 在共享内存中写入数据,并用空字节填充
print(f"Written to shared memory: {message.decode()}")
sem_read.release() # 释放读信号量,允许读者读取
time.sleep(1) # 等待1秒
except KeyboardInterrupt:
# 释放资源
sem_write.release() # 确保释放信号量,以便其他进程可以继续运行或退出
sem_read.release()
sem_write.unlink()
sem_read.unlink()
mapfile.close()
memory.unlink()
print("\nWriter shutdown")
// reader.cpp
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const char* SHARED_MEMORY_NAME = "/my_shared_memory";
const char* SEM_WRITE_NAME = "/sem_write";
const char* SEM_READ_NAME = "/sem_read";
const int MEMORY_SIZE = 1024;
bool parseStringToVector(const std::string& input, std::vector<std::vector<float>>& result) {
std::stringstream ss(input);
std::string line;
// 解析每一行(由分号分隔)
while (std::getline(ss, line, ';')) {
if (line.empty()) continue; // 忽略空行
std::vector<float> innerVector;
std::stringstream linestream(line);
std::string value;
// 解析每个值(由逗号分隔)
while (std::getline(linestream, value, ',')) {
//std::cout << value << std::endl;
float temp = 0.0;
try {
std::size_t lastChar;
temp = std::stof(value, &lastChar);
// 检查是否所有的字符都被解析了,也就是确认没有剩余的非数字字符。
if(lastChar != value.size())
return false;
}
catch (const std::invalid_argument& e) {
// 无法转换字符串为浮点数
cout << value << "无法转换字符串为浮点数" << endl;
return false;
}
catch (const std::out_of_range& e) {
// 数值超出float的范围
cout << value << "超出范围" << endl;
return false;
}
innerVector.push_back(temp);
}
if (innerVector.size() != 3) {
return false;
}
result.push_back(innerVector);
}
return true;
}
int main() {
// 打开共享内存
int shm_fd = shm_open(SHARED_MEMORY_NAME, O_RDONLY, 0666);
if (shm_fd == -1) {
perror("shm_open");
return 1;
}
// 将共享内存映射到进程地址空间
char* map_ptr = static_cast<char*>(mmap(NULL, MEMORY_SIZE, PROT_READ, MAP_SHARED, shm_fd, 0));
if (map_ptr == MAP_FAILED) {
perror("mmap");
return 1;
}
// 打开信号量
sem_t* sem_write = sem_open(SEM_WRITE_NAME, 0);
sem_t* sem_read = sem_open(SEM_READ_NAME, 0);
if (sem_write == SEM_FAILED || sem_read == SEM_FAILED) {
perror("sem_open");
return 1;
}
// 循环读取共享内存的数据
while (true) {
if (sem_wait(sem_read) < 0) { // 等待写者完成写操作
perror("sem_wait");
continue;
}
// 读取共享内存的内容
std::string read_data(map_ptr);
std::vector<std::vector<float>>vec;
bool out = parseStringToVector(read_data, vec);
if (!out) {
cout << "转换异常" << endl;
}
// 打印解析结果
for (const auto& innerVec : vec) {
for (const float& num : innerVec) {
std::cout << num << ' ';
}
std::cout << std::endl;
}
//std::cout << "Read from shared memory: " << read_data << std::endl;
if (sem_post(sem_write) < 0) { // 允许写者进入共享内存区域
perror("sem_post");
continue;
}
}
// 清理资源(实际上,由于是无限循环,所以很可能不会执行到这里)
munmap(map_ptr, MEMORY_SIZE);
close(shm_fd);
sem_close(sem_write);
sem_close(sem_read);
return 0;
}
g++ reader.cpp -o reader -lrt -lpthread
python3 writer.py
./reader