uc/os内存管理的理解
OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err) {
..............................................
plink = (void **)addr; /* Create linked list of free memory blocks当上述条件都得到满足时,所要建立的内存分区内的所有内存块链接成一个单向链表。这里之所以用单向链表,是因为在单向链表中插入和删除元素都是从链表的 顶端开始向下执行的。内存区可使用静态二维数组或者在初始化时使用malloc()建立,因为malloc()返回值为void*所以这里是 (void **)addr;其实此时plink里面存放的也是当前内存块的地址*/
pblk = (INT8U *)addr + blksize; /*pblk指向将被释放的内存控制块的指针。如果在此处不是很理解,请参看谭浩强C语言的多维数组与指针一节。其实此时pblk就是链表的下一个内存块的地址*/
for (i = 0; i < (nblks - 1); i++) { /*这里也体现了nblk应该大于等于2*/
*plink = (void *)pblk; /*在plink所指向的地址内存入指针pblk,这样此时这个plink指向的单元的头
四个字节中存入了链表的下一个内存块的地址。*/
plink = (void **)pblk; /* plink和pblk指向同一地址 (void **)pblk 这样转换了类型 但是pblk的
值并不改变,于是这样把pblk的值赋给了plink*/
pblk = pblk + blksize; /*指针pblk指向地址(plbk + blksize);这一段程序建立了一个内存分区,该内
存分区由nblks个大小为blksize的内存块组成.所有的内存块以单联表的形式连接在一起。单联表的指针域在每个内存块的头四个 字节内(一个指针占用四个字节).注意一个指针的大小决定于所用编译器 TC运行在16位模拟器中所以指针大小是16位即2字节 而 现在大多数编译器运行在32位模拟器中所以指针大小是32位即4字节。
}
.................................................................
}
c语言不够扎实,这是网上找的解说,看了好久貌似懂了。
其实就是 把pblk(一个地址)看成一个数,然后强制类型转换后赋给相应一级和二级指针,这样就形成了链表
二
void *OSMemGet (OS_MEM *pmem, INT8U *err) /*传递给OSMemGet()函数的参数中的指针pmem,它指向希望从中非配到内存块 的内存分区。*/
{
................................
if (pmem->OSMemNFree > 0) { /* See if there are any free memory blocks;OSMemGet()要检查内存分区中是否有空余的内存块。*/
pblk = pmem->OSMemFreeList; /* Yes, point to next free memory block如果有空余内存块,那么其中第 1个内存块会从空余内存块链表中被删除*/
pmem->OSMemFreeList = *(void **)pblk; /* Adjust pointer to new free list此处为什么要用*(void **)pblk 的形式 网上众说纷纭,其实我觉的很简单,因为OSMemFreeList在定义的时候就定义成了void* 见UCOS_II.H文件 这里纯粹就是 为了统一类型作的强制转换类型而已,是一种编程的好习惯。当然还是应该格外注意void*的用法。*/
pmem->OSMemNFree--; /* One less memory block in this partition空余内存块链表会被更新,包括将链表头指针后移一个元素和将空余内存块数减一。*/
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return (pblk); /* Return memory block to caller将指向已分配的内存块的指针返回给用户程序。*/
}
....................................
}
第一句:pmem->OSMemFreeList也指向空闲链表的起始地址,把这个起始赋给pblk
第二句:即把pmem->OSMemFreeList(也即pblk)指向的地址中的内容(即下一内存块的地址)赋给pmem->OSMemFreeList
难点就是 要搞清 地址 和地址中存的内容,即二级指针方面