EPICS libCom库(5) -- myfreeList

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

你可能感兴趣的:(EPICS教程,Linux,C,EPICS,C语言)