一些内存管理API

//释放页面块,释放的页面块从 page 开始,个数等于2的order次方个
void __free_pages(struct page *page, unsigned int order)
{
if (put_page_testzero(page)) {
if (order == 0)
free_hot_cold_page(page, false);
else
__free_pages_ok(page, order);
}
}


//以 gfp_mask 分配方式,分配2的order次方个连续的物理页

unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
{
struct page *page;


VM_BUG_ON((gfp_mask & __GFP_HIGHMEM) != 0);


page = alloc_pages(gfp_mask, order);
if (!page)
return 0;
return (unsigned long) page_address(page);
}


//查找一块从 start 开始,到 end 结束的线性地址,并从该地址区间

//中,创建size字节大小的虚拟内核

//区间
struct vm_struct *__get_vm_area(unsigned long size , unsigned long flags,
                unsigned long start, unsigned long end    )
{
return __get_vm_area_node(size, 1, flags, start, end, NUMA_NO_NODE,
  GFP_KERNEL, __builtin_return_address(0));
}


//基于slab分配实际上存在的连续的内存


//size 要分配的字节数,flags 分配标志 GFP_KERNEL最常见的分配方式

static __always_inline void *kmalloc(size_t size, gfp_t flags)
{
if (__builtin_constant_p(size)) {
if (size > KMALLOC_MAX_CACHE_SIZE)
return kmalloc_large(size, flags);
#ifndef CONFIG_SLOB
if (!(flags & GFP_DMA)) {
int index = kmalloc_index(size);


if (!index)
return ZERO_SIZE_PTR;


return kmem_cache_alloc_trace(kmalloc_caches[index],
flags, size);
}
#endif
}
return __kmalloc(size, flags);
}


//objp 通常是kmalloc的返回值,指向分配地址的起始
void kfree(const void *objp)
{
struct kmem_cache *c;
unsigned long flags;


trace_kfree(_RET_IP_, objp);


if (unlikely(ZERO_OR_NULL_PTR(objp)))
return;
local_irq_save(flags);
kfree_debugcheck(objp);
c = virt_to_cache(objp);
debug_check_no_locks_freed(objp, c->object_size);


debug_check_no_obj_freed(objp, c->object_size);
__cache_free(c, (void *)objp, _RET_IP_);
local_irq_restore(flags);
}


//得到通过kmalloc分配的实际内存的大小
size_t ksize(const void *objp)
{
BUG_ON(!objp);
if (unlikely(objp == ZERO_SIZE_PTR))
return 0;


return virt_to_cache(objp)->object_size;
}


//为字符串s分配一段内存空间,然后将字符串s拷贝到所分配的地址空

//间中

char *kstrdup(const char *s, gfp_t gfp)
{
size_t len;
char *buf;


if (!s)
return NULL;


len = strlen(s) + 1;
buf = kmalloc_track_caller(len, gfp);
if (buf)
memcpy(buf, s, len);
return buf;
}


//为字符串s分配一段内存空间,然后将字符串s拷贝到所分配的地址空

//间中,最多max个字节

char *kstrndup(const char *s, size_t max, gfp_t gfp)
{
size_t len;
char *buf;


if (!s)
return NULL;


len = strnlen(s, max);
buf = kmalloc_track_caller(len+1, gfp);
if (buf) {
memcpy(buf, s, len);
buf[len] = '\0';
}
return buf;
}


//同kmalloc,申请内存,但是初始化为0,归功于__GFP_ZERO
static inline void *kzalloc(size_t size, gfp_t flags)
{
return kmalloc(size, flags | __GFP_ZERO);
}


//vmalloc分配一块非连续地址空间,虚拟地址连续,但是物理地址一般不连续,用户空间不可见
//vfree释放内存
void vfree(const void *addr)
{
BUG_ON(in_nmi());


kmemleak_free(addr);


if (!addr)
return;
if (unlikely(in_interrupt())) {
struct vfree_deferred *p = this_cpu_ptr(&vfree_deferred);
if (llist_add((struct llist_node *)addr, &p->list))
schedule_work(&p->wq);
} else
__vunmap(addr, 1);
}
void *vmalloc(unsigned long size)
{
return __vmalloc_node_flags(size, NUMA_NO_NODE,
    GFP_KERNEL | __GFP_HIGHMEM);
}

猜你喜欢

转载自blog.csdn.net/dummkopfer/article/details/80521995