static void *slob_page_alloc(struct slob_page *sp, size_t size, int align) { slob_t *prev, *cur, *aligned = NULL; int delta = 0, units = SLOB_UNITS(size); for (prev = NULL, cur = sp->free; ; prev = cur, cur = slob_next(cur)) { slobidx_t avail = slob_units(cur);//计算获取的空闲块的容量 /*如果设置了对齐值则先将块进行对齐*/ if (align) { aligned = (slob_t *)ALIGN((unsigned long)cur, align); delta = aligned - cur;//计算对齐后的对象增加了多少字节的内存 } /*空闲块内存不小于要求分配的 units+对齐增量*/ if (avail >= units + delta) { /* room enough? */ slob_t *next; /*确实进行了对齐操作*/ if (delta) { /* need to fragment head to align? */ next = slob_next(cur);//获取下一个空闲块 /*这里将原本的一个块分裂成了两个块*/ set_slob(aligned, avail - delta, next);//设置空闲对象偏移aligned-->next set_slob(cur, delta, aligned);//设置空闲对象偏移cur--->aligned /*调整prev指针以及cur指针,都向后移动一个块*/ prev = cur; cur = aligned; avail = slob_units(cur);//重新获取单元数 } next = slob_next(cur);//获取下一个空闲块 if (avail == units) { /* 空闲块的大小和要求的大小完全相符 */ if (prev)//存在先驱块,则将先驱块的指针指向next块 set_slob(prev, slob_units(prev), next); else//不存在先驱块说明为第一个块,则将free直接指向next sp->free = next; } else { /* 大小不相符,则要将块分裂*/ if (prev) set_slob(prev, slob_units(prev), cur + units); else sp->free = cur + units; set_slob(cur + units, avail - units, next); } sp->units -= units;//减少slob的单元数 if (!sp->units)//单元数为0表明slob没有空闲单元,则从链表中删除 clear_slob_page_free(sp); return cur; } if (slob_last(cur)) return NULL; } }
Linux Slob分配器(二)(2)
内容版权声明:除非注明,否则皆为本站原创文章。