版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/javaxflinux/article/details/82562968
数据类型定义ctypes.h
#ifndef _CTYPES_H
#define _CTYPES_H
#if 0
#ifndef v_s8
typedef signed char v_s8;
#endif
#ifndef v_u8
typedef unsigned char v_u8;
#endif
#ifndef v_s16
typedef signed short v_s16;
#endif
#ifndef v_u16
typedef unsigned short v_u16;
#endif
#ifndef v_s32
typedef signed int v_s32;
#endif
#ifndef v_u32
typedef unsigned int v_u32;
#endif
#ifndef v_s64
typedef signed long long v_s64;
#endif
#ifndef v_u64
typedef unsigned long long v_u64;
#endif
#else
#ifndef s8
typedef signed char s8;
#endif
#ifndef u8
typedef unsigned char u8;
#endif
#ifndef s16
typedef signed short s16;
#endif
#ifndef u16
typedef unsigned short u16;
#endif
#ifndef s32
typedef signed int s32;
#endif
#ifndef u32
typedef unsigned int u32;
#endif
#ifndef s64
typedef signed long long s64;
#endif
#ifndef u64
typedef unsigned long long u64;
#endif
#ifndef Boolean
typedef unsigned char Boolean;
#endif
#endif
#endif
共享内存管理接口实现common_shm.h
#ifndef _COMMON_SHM_H_
#define _COMMON_SHM_H_
#define MAX_PROC_NUM 16
typedef enum {
MM_INIT_FIRST,
MM_INIT_OTHER
} mm_init_type_t;
/* share memory manager: block type */
typedef enum
{
SHM_START_TEST,
/* end */
SHM_BT_MAX
} mm_blk_type_t;
typedef struct {
mm_blk_type_t type;
unsigned int item_size;
unsigned int item_num;
} mm_blk_init_t;
/**
* shm_mmap - shared memory mmap.
*
* return: shm address for success. otherwise NULL.
*/
void *shm_mmap(void);
/**
* mm_init - memory manage init.
* @base_addr: start address.
* @type: init type.
*
*/
void mm_init(void *base_addr, mm_init_type_t type);
/**
* block_add - memory manage block add.
* @info: block info.
*
* return: 0 for success. otherwise -1.
*/
int block_add(mm_blk_init_t *info);
/**
* block_base_get - share memory block base address get.
* @type: block type.
*
* return: address for success. otherwise NULL.
*/
void *block_base_get(mm_blk_type_t type);
/**
* block_add_info_show - block add info show.
*
*/
void block_add_info_show(void);
/**
* m_alloc - share memory malloc.
* @type: block type.
*
* return: address for success. otherwise NULL.
*/
void *m_alloc(mm_blk_type_t type);
/**
* m_free - share memory free.
* @ptr: point for free.
*
*/
void m_free(void *ptr);
/**
* m_free2 - share memory free.
* @type: type for ptr.
* @ptr: point for free.
*
*/
void m_free2(mm_blk_type_t type, void *ptr);
#endif /*end of _COMMON_SHM_H_ */
共享内存管理接口实现common_shm.c
#include "common_shm.h"
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "ctypes.h"
#define SHM_DEBUG printf
#define SHM_ERR printf
#define SHM_MSG(fmt, argc...) {;}
#define SHM_WARN(fmt, argc...) {;}
#define MEM_BLK_HEARDER_SIZE 0x0c800000U /* 200M 用于共享内存管理 */
//#define BASE_ADDR 0x70000000U /* start address of share memory */
#define BASE_ADDR 0x7f9d9f3b7000
#define SHARE_MEMORY_SIZE (1024U*1024U*300) /* 300M size */
/* 对齐处理,转换后的值是64的倍数 */
#define CACHE_LINE 64
#define CACHE_ALIGNED(a) (((a) + CACHE_LINE - 1) & (~(CACHE_LINE - 1))) /* 1~CACHE_LINE => CACHE_LINE */
#define U32HBST(a) ((a) | 0x80000000)
#define U32HBCLR(a) ((a) & 0x7fffffff)
#define IS_U32HBST(a) (((a) & 0x80000000) != 0)
/*blk 结构放入共享内存,下面是blk管理表的表头*/
typedef struct
{
void *mem_blk_head; /*blk表头基地址,表头每一项就指向一个blk结构*/
u64 mem_blk_head_size; /*block表头大小*/
void *blk_entry_base; /*blk数据项的在共享内存的起始地址,blk连续分配*/
u64 blk_entry_size; /*blk数据项所占内存大小*/
void *mem_blk_tail; /*所有blk 管理结构表头的内存的尾地址*/
void *next_blk_base; /*下次分配blk 块的基地址*/
void *next_shm_base; /*下次分配共享内存的基地址*/
void *blk_index[0]; /*SHM_BT_MAX大小的指针数组,指向blk块的指针*/
} mm_blk_head_t;
typedef struct
{
void *head; /* block起始地址 */
void *end; /* block结束地址 */
u32 data; /* 第一个未用的item */
u32 tail; /* 最后一个未用的item */
u32 item_size; /* item大小 */
u32 type; /* item类型 */
u32 item_num; /* item的总个数 */
u32 count; /* 已分配item块计数 */
u32 index[0]; /* item索引 */
} mm_blk_t;
static mm_blk_head_t *mm_head = NULL;
static const char *mm_init_info[] = {
"\n------------------------------mm init-------------------------------------------\n"
"| mm head | blk head | blk data |... \n"
"| sizeof(mm_blk_head_t) | SHM_BT_MAX*sizeof(void *) | MEM_BLK_HEARDER_SIZE |... \n"
"--------------------------------------------------------------------------------",
NULL,
};
static void mm_info_show(const char **info)
{
while (*info) {
SHM_DEBUG("%s", *info);
info++;
}
}
static void get_len_str(unsigned int len, char *len_str, int size)
{
if (NULL == len_str) return;
if (len/1024/1024) {
snprintf(len_str, size-1, "%d(M)", len/1024/1024);
} else if (len/1024) {
snprintf(len_str, size-1, "%d(K)", len/1024);
} else {
snprintf(len_str, size-1, "%d(byte)", len);
}
}
/* cache aligned */
static inline void * cache_aligned_point(void *p)
{
char tmp[64] = {0};
u64 position = 0;
u64 result = 0;
sprintf(tmp, "%p", p);
position = strtoll(tmp, NULL, 16);
result = (position + CACHE_LINE - 1) & (~(CACHE_LINE - 1));
return p + result - position;
}
/**
* shm_mmap - shared memory mmap.
*
* return: shm address for success. otherwise NULL.
*/
void *shm_mmap(void)
{
int fd;
int len = SHARE_MEMORY_SIZE;
char dev_name[32] = "shm_file";
void *ret_val = NULL;
fd = shm_open(dev_name, O_RDWR|O_CREAT, (S_IRUSR | S_IWUSR));
if (fd < 0) {
SHM_ERR("open %s failed. error=%s", dev_name, strerror(errno));
return NULL;
}
if (ftruncate(fd, len) == -1) {
SHM_ERR("ftruncate failed");
goto err;
}
ret_val = (void *)mmap((void*)BASE_ADDR, (size_t)len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0);
if (ret_val == MAP_FAILED) {
SHM_ERR("mmap failed, errno=%s", strerror(errno));
goto err;
}
SHM_DEBUG("shm mmap success. start:%p, size:%uM", ret_val, len/(1024*1024));
close(fd);
return ret_val;
err:
close(fd);
return NULL;
}
/**
* mm_init - memory manage init.
* @base_addr: start address.
* @type: init type.
*
*/
void mm_init(void *base_addr, mm_init_type_t type)
{
if (mm_head == NULL) {
mm_head = (mm_blk_head_t *)base_addr;
mm_head = (mm_blk_head_t *)cache_aligned_point((void *)mm_head);
if (type == MM_INIT_FIRST) {
memset(base_addr, 0, SHARE_MEMORY_SIZE);
mm_head->mem_blk_head = (void *)cache_aligned_point((void *)((void *)mm_head + sizeof(mm_blk_head_t)));
mm_head->mem_blk_head_size = SHM_BT_MAX * CACHE_ALIGNED(sizeof(void*));
mm_head->blk_entry_base = (void*)cache_aligned_point((void *)((void *)mm_head->mem_blk_head
+ mm_head->mem_blk_head_size));
mm_head->blk_entry_size = MEM_BLK_HEARDER_SIZE;
mm_head->next_blk_base = (void *)(mm_head->blk_entry_base);
mm_head->mem_blk_tail = (void*)cache_aligned_point((void *)((void *)mm_head->blk_entry_base
+ mm_head->blk_entry_size));
mm_head->next_shm_base = mm_head->mem_blk_tail + CACHE_LINE;
}
SHM_DEBUG("memory manage init success");
mm_info_show(mm_init_info);
} else {
SHM_ERR("memory manage already init");
}
}
/**
* block_add - memory manage block add.
* @info: block info.
*
* return: 0 for success. otherwise -1.
*/
int block_add(mm_blk_init_t *info)
{
mm_blk_type_t type = info->type;
u32 item_size = info->item_size;
u32 item_num = info->item_num;
u64 items_len = item_size * item_num;
u64 block_size = 0;
mm_blk_t *block = NULL;
int i;
if (type > SHM_BT_MAX || 0 == item_size || 0 == item_num) {
SHM_ERR("input invalid. type:%d, item_size:%u, item_num:%u", type, item_size, item_num);
return -1;
}
/* get block size */
block_size = CACHE_ALIGNED(sizeof(mm_blk_t) + sizeof(void *) * item_num);
if((mm_head->next_blk_base + block_size) > mm_head->mem_blk_tail) {
SHM_ERR("block alloc faild(no memory). type:%d", type);
return -1;
}
/* update block info */
block = (mm_blk_t*)(mm_head->next_blk_base);
block->head = mm_head->next_shm_base;
block->end = block->head + items_len;
block->type = type;
block->item_size = item_size;
block->item_num = item_num;
block->count = 0;
block->data = 0;
block->tail = item_num - 1;
for(i = 0; i < item_num; i++) {
block->index[i] = i + 1;
}
block->index[block->tail] = 0;
/* update mm_head info */
mm_head->blk_index[type] = mm_head->next_blk_base;
mm_head->next_blk_base += block_size;
mm_head->next_shm_base += items_len;
SHM_DEBUG("block add success. type:%d", type);
return 0;
}
/**
* block_base_get - share memory block base address get.
* @type: block type.
*
* return: address for success. otherwise NULL.
*/
void *block_base_get(mm_blk_type_t type)
{
mm_blk_t *block = NULL;
/* get block by type */
block = (mm_blk_t*)(mm_head->blk_index[type]);
if (NULL == block) {
SHM_ERR("block find failed. type[%d] not block add", type);
return NULL;
}
return block->head;
}
/**
* block_add_info_show - block add info show.
*
*/
void block_add_info_show(void)
{
int i, j, type;
mm_blk_t *block_tmp = NULL;
mm_blk_t *blk_list[SHM_BT_MAX];
int total_len;
char total_len_str[32] = {0};
char item_size_str[32] = {0};
/* get all block */
for (type = 0; type < SHM_BT_MAX; type++) {
blk_list[type] = (mm_blk_t*)(mm_head->blk_index[type]);
}
/* sort by start address */
for (i = 0; i < SHM_BT_MAX; i++) {
for (j = i; j < SHM_BT_MAX; j++) {
if (blk_list[i] && blk_list[j] && blk_list[i]->head > blk_list[j]->head) {
block_tmp = blk_list[i];
blk_list[i] = blk_list[j];
blk_list[j] = block_tmp;
}
}
}
/* debug printf */
SHM_DEBUG("%-5s %-10s %-10s %-10s %-10s %-10s %-10s", "type", "start", "end", "total_len", "item_size", "total_num", "alloc_num");
for (type = 0; type < SHM_BT_MAX; type++) {
if (blk_list[type]) {
total_len = blk_list[type]->item_num * blk_list[type]->item_size;
get_len_str(total_len, total_len_str, sizeof(total_len_str));
get_len_str(blk_list[type]->item_size, item_size_str, sizeof(item_size_str));
SHM_DEBUG("%-5d %-10p %-10p %-10s %-10s %-10d %-10d",
blk_list[type]->type, blk_list[type]->head, blk_list[type]->end, total_len_str,
item_size_str, blk_list[type]->item_num, blk_list[type]->count);
}
}
}
/**
* m_alloc - share memory malloc.
* @type: block type.
*
* return: address for success. otherwise NULL.
*/
void *m_alloc(mm_blk_type_t type)
{
mm_blk_t *block = NULL;
void *p = NULL;
u32 tmp;
/* get block by type */
block = (mm_blk_t*)(mm_head->blk_index[type]);
if (NULL == block) {
SHM_ERR("block find failed. type[%d] not block add", type);
return NULL;
}
if (block->count >= block->item_num) {
SHM_ERR("Item alloc faild(no memory). type:%d", type);
return NULL;
}
/* update block info */
p = block->head + block->data * block->item_size; /* get point of first available memory */
tmp = block->index[block->data];
block->index[block->data] = U32HBST(0); /* set highest bit for malloc */
block->data = tmp; /* update first available */
block->count++;
return p;
}
/**
* m_free - share memory free.
* @ptr: point for free.
*
*/
void m_free(void *ptr)
{
int type, index = 0;
mm_blk_t *block = NULL;
/* get block by ptr */
for (type = 0; type < SHM_BT_MAX; type++) {
block = (mm_blk_t*)(mm_head->blk_index[type]);
if (NULL == block) {
continue;
}
if (ptr >= block->head && ptr < block->end) {
break; /* find */
}
}
if (NULL == block) {
SHM_ERR("block find faild. ptr:%p", ptr);
return;
}
/* clear highest bit for free */
index = (ptr - block->head) / block->item_size;
if (!IS_U32HBST(block->index[index])) {
SHM_ERR("ptr[%p] already free(Multi-free). type:%d", ptr, block->type);
return;
}
block->index[index] = 0; /* clear */
/* update block info */
if(block->count >= block->item_num) { /* first available is same with last available */
block->data = index;
block->tail = index;
block->count--;
return;
}
block->index[block->tail] = index; /* update index of last available */
block->tail = index;
block->count--;
return;
}
/**
* m_free2 - share memory free.
* @type: type for ptr.
* @ptr: point for free.
*
*/
void m_free2(mm_blk_type_t type, void *ptr)
{
int index = 0;
mm_blk_t *block = (mm_blk_t*)(mm_head->blk_index[type]);
if (NULL == block) {
SHM_ERR("block find faild. ptr:%p", ptr);
return;
}
/* clear highest bit for free */
index = (ptr - block->head) / block->item_size;
if (!IS_U32HBST(block->index[index])) {
SHM_ERR("ptr[%p] already free(Multi-free). type:%d", ptr, block->type);
return;
}
block->index[index] = 0; /* clear */
/* update block info */
if(block->count >= block->item_num) { /* first available is same with last available */
block->data = index;
block->tail = index;
block->count--;
return;
}
block->index[block->tail] = index; /* update index of last available */
block->tail = index;
block->count--;
return;
}
go语言之共享内存初始化,内存管理结构初始化,共享内存设值shm.go
package main
//#cgo linux LDFLAGS: -lrt
//#include <stdlib.h>
//#include "common_shm.h"
import "C"
import "unsafe"
import (
"time"
)
func main() {
C.mm_init(C.shm_mmap(), 0)
var info C.mm_blk_init_t = C.mm_blk_init_t{C.SHM_START_TEST, 1024, 1}
C.block_add(&info)
var p *C.int
p = (*C.int)( unsafe.Pointer( C.m_alloc(C.SHM_START_TEST) ) )
*p = 100
var i int = 0
for true {
i++
*p = C.int(i)
time.Sleep(1e9 * 1)
}
}
c语言共享内存访问数据main.c
#include <stdio.h>
#include <string.h>
#include "common_shm.h"
int main()
{
char *str;
//mm_init(shm_mmap(), 0);
mm_init(shm_mmap(), 1);
/*
mm_blk_init_t info;
info.type = SHM_START_TEST;
info.item_size = 1024;
info.item_num = 1;
block_add(&info);
*/
while(1) {
str = block_base_get(SHM_START_TEST);
if (str == NULL) {
printf("str is NUll.\n");
} else {
printf("str is not NUll.\n");
//strcpy(str, "hello");
printf("str is %d.\n", *(int *)str);
}
sleep(1);
}
}
go编译:go build
c编译:gcc -g main.c common_shm.c -o main -lrt
运行截图: