linux下go和c有内存管理的共享内存通信

版权声明:本文为博主原创文章,未经博主允许不得转载。 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

运行截图:

猜你喜欢

转载自blog.csdn.net/javaxflinux/article/details/82562968