嵌入式操作系统
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

6.4.5 malloc函数和free函数的实现

malloc函数和free函数是标准C运行期库函数,实现这两个函数对于代码的移植十分有意义。很明显,采用HeapAlloc和HeapFree函数可以很容易地模拟这两个函数,但HeapAlloc函数和HeapFree函数都接受一个堆对象指针作为参数,而malloc函数和free函数则没有。因此,为了屏蔽这个差异,我们在核心线程对象(__KERNEL_THREAD_OBJECT)中引入一个默认堆的变量,所有malloc函数和free函数的内存申请都从默认堆中进行。

下面是malloc函数的实现代码。

LPVOID malloc(DWORD dwSize)
    {
    DWORD          dwFlags =NULL;
    LPVOID          lpResult =NULL;
    __HEAP_OBJECT*   lpHeapObj=NULL;
    DWORD          dwHeapSize=0L;
    if(0==dwSize)  //Invalid parameter.
        return lpResult;
    if(NULL==CURRENT_KERNEL_THREAD->lpDefaultHeap)
                                          //Should create one.
    {
        dwHeapSize=(dwSize+sizeof(__FREE_BLOCK_HEADER) > DEFAULT_
VIRTUAL_AREA_SIZE) ?
            (dwSize+sizeof(__FREE_BLOCK_HEADER)) : DEFAULT_VIRTUAL_
AREA_SIZE;
        lpHeapObj=CreateHeap(dwHeapSize);
        if(NULL==lpHeapObj)  //Can not create heap object.
            return lpResult;
        //__ENTER_CRITICAL_SECTION(NULL,dwFlags);
        CURRENT_KERNEL_THREAD->lpDefaultHeap=(LPVOID)lpHeapObj;
        //__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
    }
    else
    {
        lpHeapObj=(__HEAP_OBJECT*)CURRENT_KERNEL_THREAD->lpDefaultHeap;
    }
    return HeapAlloc(lpHeapObj,dwSize);
    }

首先,该函授判断当前线程的默认堆对象(lpDefaultHeap)是否存在,若存在(不为NULL),则直接以默认堆为目标堆,调用HeapAlloc函数把该函数的结果返回给用户,否则,该函数首先调用CreateHeap函数创建一个默认堆,并初始化当前线程的lpDefaultHeap变量,在此基础上,再调用HeapAlloc函数。

很明显,只有malloc函数第一次调用的时候才可能会发生lpDefaultHeap为NULL的情况,后续调用的时候,不会出现这种情况。

对于free函数,实现起来就更简单了。

    VOID free(LPVOID lpMemory)
    {
    __HEAP_OBJECT*     lpHeapObj=NULL;
    if(NULL==lpMemory)
        return;
    lpHeapObj=(__HEAP_OBJECT*)CURRENT_KERNEL_THREAD->lpDefaultHeap;
    if(NULL==lpHeapObj)   //Invalid case.
        return;
    HeapFree(lpMemory,lpHeapObj);
}

首先,该函数确保当前线程的默认堆是存在的,然后调用HeapFree函数来释放具体的内存。否则可能是一种不正常操作,直接导致free函数返回。