linux kmalloc 函数

本文详细比较了kmalloc和vmalloc在内核内存分配中的异同,着重讲解了kmalloc的内存限制、工作原理与测试案例,以及它们在连续性和大块内存分配上的区别。同时介绍了相关的API和释放接口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作用:内核分配连续物理内存的接口函数,在虚拟地址空间上也是连续的。

与vmalloc的比较: 

            相同点:都是用于内核空间内存分配,对应的虚拟地址空间连续,且按字节为单位。

           异同点:kmalloc分配的物理内存是连续的,vmalloc分配的物理内存可以不连续,但是虚拟地址空间连续。kmalloc分配的物理内存受限于页面最高阶数及页面大小,vmalloc则只受限于系统内存大小。kmalloc既支持大块内存分配也支持小块内存分配,大块内存使用页面分配器,小内存使用slab分配器,而vmalloc用于大块内存分配器,并且最好分配内存大小是整页级的,否则会导致内存空间浪费。

一次分配的最大内存数量,不能超过系统页面最高阶数,比如页面最高阶数MAX_ORDER为11,那么最大的分配内存数量为 2^10 * 4K = 4M,在__alloc_pages里限制。调用栈如下:

kmalloc
  |-> kmalloc_large # 分配内存大于一个页面
  |    |-> kmalloc_order_trace
  |            |-> kmalloc_order
  |                    |-> alloc_pages # 调用物理页面分配器分配内存
  |                            |-> alloc_pages_node
  |                                    |-> __alloc_pages_node
  |                                            |-> __alloc_pages # 检查分配页面阶数是否大于等于最高阶
  |                                                    
  |
  |
  |-> __kmalloc # 分配内存小于一个页面,通过slab分配器分配内存
         |-> __do_kmalloc
                 |-> kmalloc_slab
                 |     |-> kmalloc_caches    
                 |-> slab_alloc
                         |-> slab_pre_alloc_hook
                         |-> kfence_alloc
                         |-> cache_alloc_debugcheck_before
                         |-> __do_cache_alloc
                         |-> cache_alloc_debugcheck_after
                         |-> prefetchw
                         |-> slab_want_init_on_alloc
                         |-> slab_post_alloc_hook

测试代码kmalloc_test.c

// kmalloc_test.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>


static int *p = NULL;

static int __init kmalloc_test_init(void)
{
	p = kmalloc(4 * 1024 * 1024, GFP_KERNEL);		
	printk(KERN_INFO "address: %p\n", p);
	return 0;
}

static void __exit kmalloc_test_exit(void)
{
	printk("exit\n");
	if (p != NULL)
		kfree(p);
}

module_init(kmalloc_test_init);
module_exit(kmalloc_test_exit);
MODULE_LICENSE("GPL");

Makefile如下:

obj-m+=kmalloc_test.o
CONFIG_MODULE_SIG=n
all:
	make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
clean:
	make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean

测试结果如下图所示,插入内核模块分配一块4M(阶数为10)大小的物理内存块,对应的阶数为10,阶数为10的内存块从548减少为547,删除内核模块回收内存块,阶数为10的内存块数量增加一,变为548。

kmalloc提供的分配内存接口:

// 头文件 <linux/slab.h>

kmalloc:分配连续物理内存空间,内存地址上的内容随机。
kzalloc:分配连续物理内存,并将所分配内存空间设置为0。
kmalloc_node:指定的numa节点上分配连续物理内存空间。
kzalloc_node:指定的numa节点上分配连续的物理内存空间,并设置为0。

上述分配接口对应的释放内存接口:kfree


kvmalloc:根据分配内存大小调用kmalloc,或vmalloc,防止内存分配失败。
kvzalloc:根据分配内存大小调用kmalloc或vmalloc分配物理内存。
kvmalloc_node:指定的numa节点上根据分配内存大小调用kmalloc或vmalloc分配物理内存,防止内存分配失败。
kvmalloc_array:同kvzalloc,一次性分配多个,并返回数组。
kvcalloc:同kvmalloc_array,并将分配的内存空间设置为0.

对应的释放内存接口:kvfree

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值