内核态用vmalloc申请大块内存

内核态用vmalloc申请大块内存

   

 

       本文欢迎自由转载,请标明出处,并保证本文的完整性。


经常在内核版看到网友发帖,问如何在内核态申请大块内存,上百兆甚至上G的内存。用kmalloc或get_free_pages都不能满足这样的要求。今天又在内核版看到这样的帖子,其中白金兄回复说可以用vmalloc实现,并且给出了例程。本人也进行了实践,初步看来是分配成功了,但至于是否可以有效的应用于生产环境还有待于验证。本文的总结仅作为学习环境上的探讨和时间。

以下是申请大块内存的代码。代码是以白金兄提供的代码(http://linux.chinaunix.net/bbs/viewthread.php?tid=1139485&page=2#pid7139143)为蓝本,本人仅添加了传递模块参数的代码。传递的模块参数为申请内存的大小,单位为Mbyte。


#include <linux/module.h>

#include <linux/vmalloc.h>

MODULE_AUTHOR("platinum");

MODULE_DESCRIPTION("This is a module sample.");

MODULE_LICENSE("GPL");

/*Godbach added module parameter*/

static int memsize = 100;/*Unit: Mbyte*/

module_param(memsize, int, S_IRUGO);

__u8 *data;

int

init_module (void)

{

data = vmalloc(1024 * 1024 * memsize);

if (!data)

return -ENOMEM;

memset(data, 0xff, 1024 * 1024 * memsize);

printk("module loaded.\n");

return 0;

}

void

cleanup_module(void)

{

vfree(data);

printk("module unloaded.\n");

}

本人的内核版本是2.6.18.3。编译该内核模块,生成alloc_large_mem.ko.

以下是默认申请100M内存时系统前后内存的变化。

[root@localhost alloc_large_mem]# free
             total       used       free     shared    buffers     cached
Mem:        385624     188760     196864          0       1908      54936
-/+ buffers/cache:     131916     253708
Swap:       522104       8068     514036
[root@localhost alloc_large_mem]# insmod alloc_large_mem.ko
[root@localhost alloc_large_mem]# free
             total       used       free     shared    buffers     cached
Mem:        385624     290388      95236          0       1960      54948
-/+ buffers/cache:     233480     152144
Swap:       522104       8068     514036
[root@localhost alloc_large_mem]#

由此可见,insmod模块之后系统使用的内粗增加了100M多一点。

那么,另外一个问题,vmalloc可以分配的内存上限是多少呢?参考白金兄的说法,vmalloc分配的内存上限是和cat /proc/meminfo中VmallocTotal的值有关的。我这里的显示结果为:


[root@localhost alloc_large_mem]# cat /proc/meminfo

……

VmallocTotal:  638968 kB

VmallocUsed:      3512 kB

VmallocChunk:  633644 kB


因此,vmalloc最大可分配的内存为600M,由于我的剩余物理内存只有200M左右。所以这里尝试300M的内存观察一下结果。


[root@localhost alloc_large_mem]# free

total       used       free    shared    buffers     cached

Mem:       385624     101216     284408          0       4348     46800

-/+ buffers/cache:      50068    335556

Swap:      522104      88400     433704

[root@localhost alloc_large_mem]# cat /proc/meminfo | grep Vmalloc

VmallocTotal:  638968 kB

VmallocUsed:      3512 kB

VmallocChunk:  633644 kB

[root@localhost alloc_large_mem]#

[root@localhost alloc_large_mem]# insmod alloc_large_mem.ko memsize=300

[root@localhost alloc_large_mem]# free

total       used       free    shared    buffers     cached

Mem:       385624     380040       5584          0       1796     21896

-/+ buffers/cache:     356348     29276

Swap:      522104      88400     433704

[root@localhost alloc_large_mem]# cat /proc/meminfo | grep Vmalloc

VmallocTotal:  638968 kB

VmallocUsed:   311032kB

VmallocChunk:  326440 kB

[root@localhost alloc_large_mem]#


这里测试的情况是虚拟内存的使用情况却是增加了300M左右,而物理内存基本上已经耗尽了。

白金兄曾经测试在启动时 kernel 里 vmalloc=1280M,然后insmod内核模块成功分配到1G的内存。我也曾测试分配500M或400M的情况(虚拟内存上限600多M),但都失败了:


[root@localhost alloc_large_mem]# insmod alloc_large_mem.ko memsize=500

insmod: error inserting 'alloc_large_mem.ko':-1 Cannot allocate memory

[root@localhost alloc_large_mem]# insmod alloc_large_mem.ko memsize=400

insmod: error inserting 'alloc_large_mem.ko':-1 Cannot allocate memory


究其原因,应该是超过了内核启动时默认的vmalloc的值,可以通过指定内核启动时vmalloc=xxx来解决。

以上是用vmalloc申请大块内存的总结。不足之处,请大家多多指教。

在Linux系统中,请求大块内核内存通常是通过预留(Reserving)和分配(Allocating)的过程来完成的,特别是在需要管理某些特殊内存区域的时候,比如驱动程序或某些内存敏感的服务。以下是基本步骤: 1. **预留内存** (Memory Caching or Buffering): 可以使用`kmalloc()`或`vmalloc()`函数预留内存,它们会在内核的堆区为你的进程保留一块指定大小的内存。`kmalloc()`适用于小到中等大小的内存块,而`vmalloc()`则更适合于请求非常大的连续内存区域。 ```c void *ptr = kmalloc(size, GFP_KERNEL); // 使用普通内核上下文(GFP_KERNEL) void *ptr = vmalloc(size); // 请求较大内存,自动填充零值 ``` 2. **内存池管理**: 对于频繁的内存分配和释放,可以创建自定义内存池,例如`slab allocator`或`kmem_cache`,它们允许更高效地管理和回收内存块。 3. **内存区域(Memory Domains)**: 如果有特定的需求,还可以利用`request_memcg_node()`来请求内存域内的内存,这允许对内存的使用进行更细粒度的控制。 4. **内存碎片收集**: `hugepages`是一种较大的内存页,可以直接避免因小页分配产生的大量碎片。可以使用`huge_page_order()`函数获取合适的页面大小,然后通过`request_hugepages()`来申请。 5. **设备驱动程序**: 设备驱动程序通常会在初始化阶段为自身申请大块内存,这通常在模块加载时完成,比如`ioremap`用于映射物理内存。 注意在使用大内存时,一定要确保正确的释放机制,避免内存泄露。另外,因为内核内存有限,过度占用可能会导致系统稳定性问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值