Linux下提供了多种共享内存的通讯机制,常用的就是socket,但是socket通讯使用简单,但性能不佳,最优的方式还是共享内存方式。本章分享封装库,就是基于共享内存实现的。
封装库连接
(66条消息) 互斥锁+共享内存封装库,实现进程间通讯(Linux)-C文档类资源-CSDN文库
共享内存Linux提供了三种方式:
- POSIX共享内存对象
- POSIX内存映射文件
- SYSTEM V共享内存
这三种方式的区别,就不分析了,大家可以网上检索一下。
本章分享的基于第二种方式“POSIX内存映射文件”实现的。
设计的要求
1:使用进程间的互斥锁,实现了共享内存共享数据的互斥访问问题
2:有效数据部分,通过分配器来管理内存的开辟和释放
3:实现了一对多的订阅/发布模型(一端发送,多端接收的模型)
设计的架构图
接口定义
#ifndef __DEVIN_SHM_FIFO_H__
#define __DEVIN_SHM_FIFO_H__
void *devin_shm_fifo_init(char *topic);
void devin_shm_fifo_destory(void *handle);
int devin_shm_fifo_read(void *handle, void *buf, int max_buf_len, int *datalen);
// 写入端有一次拷贝 (将数据拷贝到共享内存区域)
int devin_shm_fifo_write(void *handle, const void *data, int datalen);
// 零拷贝的操作 (仅用于发送或写入端)
// 从共享内存中获的可用的空间,返回地址
int devin_shm_fifo_get_addr(void *handle, void **addr, void **addr_param, int datalen);
// 数据写入共享内存后,及时同步到接收端
int devin_shm_fifo_write_sync(void *handle, void *addr, void *addr_param, int datalen);
#endif
接口使用示例
// 订阅方
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include "devin_shm_fifo.h"
int main()
{
char *topic = "topic";
void *shmfifo = NULL;
char buffer[1024*1024*3] = {0};
int i = 0;
int ret = -1;
struct timeval cur_time;
int datalen = 0;
shmfifo = devin_shm_fifo_init(topic);
if(!shmfifo)
{
printf("devin_shm_fifo_init fail\n");
return -1;
}
int mm = 0;
while (1)
{
memset(buffer, 0, sizeof(buffer));
ret = devin_shm_fifo_read(shmfifo, buffer, sizeof(buffer), &datalen);
if(ret == 0)
{
gettimeofday(&cur_time,NULL);
printf("%05d, %s, %ld\n", mm++, buffer, cur_time.tv_sec * 1000000 + cur_time.tv_usec);
}else{
//printf("xxxxxxx : %d\n", ret);
}
usleep(5*1000);
}
devin_shm_fifo_destory(shmfifo);
return 0;
}
// 发布方:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include "devin_shm_fifo.h"
int main()
{
char *topic = "topic";
void *shmfifo = NULL;
char buffer[1024*1024*3] = {0};
int i = 0;
int ret = -1;
void *addr = NULL;
void *addr_param = NULL;
struct timeval cur_time;
shmfifo = devin_shm_fifo_init(topic);
if(!shmfifo)
{
printf("shmfifo_init fail\n");
return -1;
}
while (1)
{
memset(buffer, 0, sizeof(buffer));
gettimeofday(&cur_time,NULL);
snprintf(buffer, sizeof(buffer), "aaaaa%05d, time: %ld", i++, cur_time.tv_sec * 1000000 + cur_time.tv_usec);
send:
// 获取指定大小的空间地址
ret = devin_shm_fifo_get_addr(shmfifo, &addr, &addr_param, sizeof(buffer));
if(ret < 0)
{
printf("devin_shm_fifo_get_addr ret = %d\n", ret);
goto send;
}
// 给空间填充数据
memcpy(addr, buffer, sizeof(buffer));
// 数据同步到接收端
ret = devin_shm_fifo_write_sync(shmfifo, addr, addr_param, sizeof(buffer));
if(ret < 0)
{
printf("devin_shm_fifo_write_sync ret = %d\n", ret);
}else{
printf("%s\n", buffer);
}
usleep(10*1000);
}
//void shmfifo_get(shmfifo_t *fifo, void *buf);
devin_shm_fifo_destory(shmfifo);
return 0;
}