2025-03-08
动态内存分配是一个很重要的功能,如果没有动态内存分配,所有的变量都分配到堆上,堆栈很容易就会溢出。动态内存分配一般都是用来分配需要长期使用的内存或大块的内存。不过在Linux内核中,分配内存会比在应用层要复杂。下面就给了一个小例子。
kmalloc
:虚拟/物理地址是连续的
kzalloc
:会将内存初始化为0, 虚拟/物理地址是连续的
kvmalloc
:不限制内存大小,但是只保证虚拟内存地址连续,物理地址空间不一定连 续。并且可能会产生阻塞或休眠
GFP_KERNEL
:分配内存时可能会阻塞或休眠
GFP_ATOMIC
:分配内存时不会休眠
//simple.c
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
static int __init simple_init(void) {
/* ===================== kmalloc =================== */
char *ptr_1 = kmalloc(64, GFP_KERNEL);
if (!ptr_1) {
pr_err("kmalloc 64 bytes failed\n");
} else {
kfree(ptr_1);
pr_info("kmalloc 64 bytes ok\n");
}
/* ===================== kzalloc =================== */
char *ptr_2 = kzalloc(64, GFP_KERNEL);
if (!ptr_2) {
pr_err("kzalloc 64 bytes failed\n");
} else {
kfree(ptr_2);
pr_info("kzalloc 64 bytes ok\n");
}
/* ===================== kvmalloc =================== */
const int max_memory_size = 1024 * 1024;
char *ptr_3 = kvmalloc(2 * max_memory_size, GFP_KERNEL);
if (!ptr_3) {
pr_err("kvmalloc %d bytes failed\n", 2 * max_memory_size);
} else {
kfree(ptr_3);
pr_info("kvmalloc %d bytes ok\n", 2 * max_memory_size);
}
return 0;
}
static void __exit simple_exit(void) { pr_info("simple_exit\n"); }
module_init(simple_init);
module_exit(simple_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("heng30");
MODULE_VERSION("v0.0.1");
MODULE_DESCRIPTION("A simple kernel module");
#!/bin/sh
top-dir = $(shell pwd)
kernel-version = $(shell uname -r)
kernel-dir ?= /lib/modules/$(kernel-version)/build
obj-m += simple.o
all:
make -C $(kernel-dir) modules M=$(top-dir)
clean:
rm -f *.o *.ko *.mod *.mod.c *.order *.symvers
make -C $(kernel-dir) clean m=$(top-dir)
安装驱动:insmod simple.ko
移除驱动:rmmod simple.ko