myfreeList.h描述了分配和释放固定尺寸内存元素的例程。在一个空闲列表中维护空闲元素,而不是通过调用free被返回这个堆。当调用malloc()是必要时,以元素尺寸的倍数分配内存。这个myfreeList.h是模仿EPICS libCom库中freeList.h中的函数编写的。
#ifndef INCmyfreeListh
#define INCmyfreeListh
#include
#include "libComAPI.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct allocMem{
struct allocMem *next;
void * memory;
}allocMem;
typedef struct {
int size;
int nmalloc;
void * head; // 指向下次分配的内存单元
allocMem * mallochead; // 分配的内存组的头,每块内存组中由nmalloc个size大小的内存单元。
size_t nBlocksAvailable;// 有多少内存单元可分配
epicsMutexId lock;
}FREELISTPVT;
void myfreeListInitPvt(void **ppvt, int size, int malloc);
void * myfreeListCalloc(void *pvt);
void * myfreeListMalloc(void *pvt);
void myfreeListFree(void *pvt,void*pmem);
void myfreeListCleanup(void *pvt);
size_t myfreeListItemsAvail(void *pvt);
#ifdef __cplusplus
}
#endif
#endif /*INCmyfreeListh*/
此处:
1)pvt:为了由freelist库内部使用。调用者必须提供用于一个void *pvt的存储区。
2)size:每个元素字节为单位的尺寸。主要所有元素必须是相同尺寸。
3)nmalloc:当必须调用常规的malloc()时,要分配的元素数目。
#include
#include
#include
#include "cantProceed.h"
#include "epicsMutex.h"
#include "myfreeList.h"
#include "adjustment.h"
/* 初始化一个结构体FREELISTPVT */
void myfreeListInitPvt(void ** ppvt, int size,int nmalloc)
{
FREELISTPVT * pfl;
pfl = callocMustSucceed(1, sizeof(FREELISTPVT), "myfreeListInitPvt");
pfl->size = adjustToWorstCaseAlignment(size); // 内存单元大小是内存对齐的
pfl->nmalloc = nmalloc;
pfl->head = NULL;
pfl->mallochead = NULL;
pfl->nBlocksAvailable = 0u;
pfl->lock = epicsMutexMustCreate();
*ppvt = (void *)pfl;
return;
}
/* 返回一个内存单元的空间(大小为size个字节) */
void * myfreeListMalloc(void * pvt)
{
FREELISTPVT * pfl = pvt;
void * ptemp;
void ** ppnext;
allocMem * pallocMem;
int i;
epicsMutexMustLock(pfl->lock);
ptemp = pfl->head;
if (ptemp == NULL){
ptemp = (void *)malloc(pfl->nmalloc * pfl->size);
if (ptemp == NULL){
epicsMutexUnlock(pfl->lock);
return NULL;
}
pallocMem = (allocMem *)calloc(1, sizeof(allocMem));
if (pallocMem == NULL){
epicsMutexUnlock(pfl->lock);
free(ptemp);
return NULL;
}
pallocMem->memory = ptemp;
if (pfl->mallochead){
pallocMem->next = pfl->mallochead;
}
pfl->mallochead = pallocMem;
for(i = 0; i < pfl->nmalloc; i++){
ppnext = ptemp;
* ppnext = pfl->head;
pfl->head = ptemp;
ptemp= ((char *)ptemp) + pfl->size;
}
ptemp = pfl->head;
pfl->nBlocksAvailable += pfl->nmalloc;
}
ppnext = pfl->head;
pfl->head = * ppnext;
pfl->nBlocksAvailable--;
epicsMutexUnlock(pfl->lock);
return ptemp;
}
void * myfreeListCalloc(void * pvt)
{
FREELISTPVT * pfl= pvt;
void * ptemp;
ptemp = myfreeListMalloc(pvt);
if (ptemp){
memset((char *)ptemp, 0, pfl->size);
}
return ptemp;
}
/* 把内存pmem放入结构体FREELISTPVT */
void myfreeListFree(void * pvt, void * pmem)
{
FREELISTPVT * pfl = pvt;
void ** ppnext;
epicsMutexMustLock(pfl->lock);
ppnext = pmem;
* ppnext = pfl->head;
pfl->head = pmem;
pfl->nBlocksAvailable++;
epicsMutexUnlock(pfl->lock);
}
/* 释放所有FREELISTPVT结构体中所有分配的内存,以及FREELISTPVT结构体所占空间 */
void myfreeListCleanup(void * pvt)
{
FREELISTPVT * pfl = pvt;
allocMem * phead;
allocMem * pnext;
phead = pfl->mallochead;
while (phead){
pnext = phead->next;
free(phead->memory);
free(phead);
phead = pnext;
}
epicsMutexDestroy(pfl->lock);
free(pvt);
}
/* 查看FREELISTPVT结构体中还有多少个内存单元可分配 */
size_t myfreeListItemsAvail(void * pvt)
{
FREELISTPVT * pfl = pvt;
size_t nBlocksAvailable;
epicsMutexMustLock(pfl->lock);
nBlocksAvailable = pfl->nBlocksAvailable;
epicsMutexUnlock(pfl->lock);
return nBlocksAvailable;
}
以下是测试以上myfreeList.h中定义的例程的程序代码:
#include
#include "myfreeList.h"
typedef struct Student{
char name[20];
char sex;
int age;
}Student;
void print_info(Student * pstu)
{
printf("name: %s, sex: %d, age: %d\n", pstu->name, pstu->sex, pstu->age);
}
int main(int argc, char ** argv)
{
void * pvt = NULL;
int nmalloc = 10;
int size = sizeof(Student);
Student * pstu = NULL;
Student ** stacks = (Student **)malloc(sizeof(Student *) * 10);
int index = 0;
myfreeListInitPvt(&pvt, size, nmalloc);
pstu = (Student *)myfreeListMalloc(pvt);
printf("origal size: %ld\n", myfreeListItemsAvail(pvt));
strcpy(pstu->name, "LiLei");
pstu->sex = 'M';
pstu->age = 9;
stacks[index++] = pstu;
pstu = (Student *)myfreeListMalloc(pvt);
strcpy(pstu->name, "HanMeimei");
pstu->sex = 'F';
pstu->age = 8;
stacks[index++] = pstu;
printf("Free %ld items available\n", myfreeListItemsAvail(pvt));
while (index > 0){
pstu = stacks[--index];
print_info(pstu);
myfreeListFree(pvt, pstu);
printf("Free %ld items available\n", myfreeListItemsAvail(pvt));
}
myfreeListCleanup(pvt);
return 0;
}
编译以上代码,测试结果如下:
orangepi@orangepi4-lts:~/host_program/host/hostApp$ O.linux-aarch64/myfreeListTest
origal size: 9
Free 8 items available
name: HanMeimei, sex: 70, age: 8
Free 9 items available
name: LiLei, sex: 77, age: 9
Free 10 items available