一、前言
當(dāng)設(shè)備長(zhǎng)時(shí)間運(yùn)行后,內(nèi)存碎片化,很難找到連續(xù)的物理頁(yè)。在這種情況下,如果需要分配長(zhǎng)度超過(guò)一頁(yè)的內(nèi)存塊,可以使用不連續(xù)頁(yè)分配器,分配虛擬地址連續(xù)但是物理地址不連續(xù)的內(nèi)存塊。在 32 位系統(tǒng)中不連分配器還有一個(gè)好處:優(yōu)先從高端內(nèi)存區(qū)域分配頁(yè),保留稀缺的低端內(nèi)存區(qū)域。
二、編程接口
2.1、內(nèi)核提供的vmalloc函數(shù)接口
-
vmalloc:分配不連續(xù)的物理地址空間,但虛擬內(nèi)存地址是連續(xù)的。
-
vfree:配套,釋放 vmalloc 分配的內(nèi)存地址。
2.2、內(nèi)核提供的kmalloc函數(shù)接口
-
kmalloc:分配物理連續(xù)的內(nèi)存地址(則虛擬地址自然連續(xù),基于 slab)。
-
kfree:配套,釋放 kmalloc 分配的內(nèi)存地址。
2.3、數(shù)據(jù)結(jié)構(gòu)
struct vm_struct {
struct vm_struct *next;
void *addr;
unsigned long size;
unsigned long flags;
struct page **pages;
unsigned int nr_pages;
phys_addr_t phys_addr;
const void *caller;
};
struct vmap_area {
unsigned long va_start;
unsigned long va_end;
struct rb_node rb_node; /* address sorted rbtree */
struct list_head list; /* address sorted list */
/*
* The following three variables can be packed, because
* a vmap_area object is always one of the three states:
* 1) in "free" tree (root is vmap_area_root)
* 2) in "busy" tree (root is free_vmap_area_root)
* 3) in purge list (head is vmap_purge_list)
*/
union {
unsigned long subtree_max_size; /* in "free" tree */
struct vm_struct *vm; /* in "busy" tree */
struct llist_node purge_list; /* in purge list */
};
};
- 每個(gè)虛擬內(nèi)存區(qū)域?qū)?yīng)一個(gè) vmap_area 實(shí)例;
- 每個(gè) vmap_area 實(shí)例關(guān)聯(lián)一個(gè) vm_struct 實(shí)例;
三、vmalloc的使用示例
分配不連續(xù)的物理地址空間,但虛擬內(nèi)存地址是連續(xù)的。
- 定義初始化模塊和退出模塊函數(shù)。
- 定義一個(gè)全局變量。
- 在初始化模塊函數(shù)調(diào)用vmalloc函數(shù),申請(qǐng)內(nèi)存。
- 退出模塊調(diào)用vfree釋放內(nèi)存。
- 模塊初始化操作和退出函數(shù)調(diào)用module_init()和module_exit()。
- 其他的聲明信息,比如許可協(xié)議、作者、模塊功能描述等等。
vmtest.c
/* 頭文件和全局變量地聲明*/
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/module.h>
static int __init vmalloc_InitFunc(void);
static void __exit vmalloc_ExitFunc(void);
#define MEMORY_SIZE 4096
char * pmymemory;
// 模塊初始化函數(shù)
int __init vmalloc_InitFunc(void)
{
pmymemory = (char *)vmalloc(MEMORY_SIZE);
if(pmymemory == NULL )
printk("執(zhí)行:vmalloc(...)函數(shù)分配內(nèi)存失敗! \n");
else
printk("執(zhí)行:vmalloc(...)函數(shù)成功,地址 = 0x%lx\n", (unsigned long)pmymemory);
return 0;
}
// 模塊退出函數(shù)
void __exit vmalloc_ExitFunc(void)
{
if(NULL != pmymemory)
{
vfree(pmymemory);
printk("調(diào)用:vfree(...)釋放內(nèi)存成功!\n");
}
printk("正常:內(nèi)核模塊退出成功!\n");
}
/* 模塊初始化操作和退出函數(shù)調(diào)用 */
module_init(vmalloc_InitFunc);
module_exit(vmalloc_ExitFunc);
MODULE_LICENSE("GPL"); /* 描述模塊代碼接受的軟件許可協(xié)議 */
MODULE_AUTHOR("Lion Long"); /* 描述模塊的作者信息:包括作者姓名及郵箱等等 */
MODULE_DESCRIPTION(" kernel module : vmalloc/vfree"); /* 簡(jiǎn)要描述此模塊用途及功能介紹*/
Makefile
obj-m:=vmtest.o
CURRENT_PAHT:=$(shell pwd)
LINUX_KERNEL:=$(shell uname -r)
LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PAHT) modules
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PAHT) cleals
(1)make。
$ make
make -C /usr/src/linux-headers-4.15.0-142-generic M=/home/fly/workspace/vmalloctest modules
make[1]: Entering directory '/usr/src/linux-headers-4.15.0-142-generic'
CC [M] /home/fly/workspace/vmalloctest/vmtest.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/fly/workspace/vmalloctest/vmtest.mod.o
LD [M] /home/fly/workspace/vmalloctest/vmtest.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.15.0-142-generic'
$ ls
Makefile modules.order Module.symvers vmtest.c vmtest.ko vmtest.mod.c vmtest.mod.o vmtest.o
(2)插入模塊。
# insmod vmtest.ko
# dmesg -c
[159699.561428] 執(zhí)行:vmalloc(...)函數(shù)成功,地址 = 0xffffa6aec0668000
四、kmalloc的使用示例
分配物理連續(xù)的內(nèi)存地址(則虛擬地址自然連續(xù),基于 slab)。
- 定義初始化模塊和退出模塊函數(shù)。
- 定義一個(gè)全局變量。
- 在初始化模塊函數(shù)調(diào)用kmalloc函數(shù),申請(qǐng)內(nèi)存。
- 退出模塊調(diào)用kfree釋放內(nèi)存。
- 模塊初始化操作和退出函數(shù)調(diào)用module_init()和module_exit()。
- 其他的聲明信息,比如許可協(xié)議、作者、模塊功能描述等等。
kmtest.c
/* 頭文件和全局變量地聲明*/
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
static int __init kmalloc_InitFunc(void);
static void __exit kmalloc_ExitFunc(void);
#define MEMORY_SIZE 4096
char * pmymemory;
// 模塊初始化函數(shù)
int __init kmalloc_InitFunc(void)
{
pmymemory = (char *)kmalloc(MEMORY_SIZE,GFP_KERNEL);
if(pmymemory == NULL )
printk("執(zhí)行:kmalloc(...)函數(shù)分配內(nèi)存失敗! \n");
else
{
// /*輸出分配的內(nèi)存空間的起始地址*/
printk("執(zhí)行:kmalloc(...)函數(shù)成功,地址 = 0x%lx\n", (unsigned long)pmymemory);
}
return 0;
}
// 模塊退出函數(shù)
void __exit kmalloc_ExitFunc(void)
{
if(NULL != pmymemory)
{
kfree(pmymemory);
printk("調(diào)用:kfree(...)釋放內(nèi)存成功!\n");
}
printk("正常:內(nèi)核模塊退出成功!\n");
}
/* 模塊初始化操作和退出函數(shù)調(diào)用 */
module_init(kmalloc_InitFunc);
module_exit(kmalloc_ExitFunc);
MODULE_LICENSE("GPL"); /* 描述模塊代碼接受的軟件許可協(xié)議 */
MODULE_AUTHOR("Lingshengedu"); /* 描述模塊的作者信息:包括作者姓名及郵箱等等 */
MODULE_DESCRIPTION(" kernel module : kmalloc/kfree"); /* 簡(jiǎn)要描述此模塊用途及功能介紹*/
Makefile
obj-m:=kmkf.o
CURRENT_PAHT:=$(shell pwd)
LINUX_KERNEL:=$(shell uname -r)
LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PAHT) modules
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PAHT) cleals
(1)make。
# make
make -C /usr/src/linux-headers-4.15.0-142-generic M=/home/fly/workspace/kmalloctest modules
make[1]: Entering directory '/usr/src/linux-headers-4.15.0-142-generic'
CC [M] /home/fly/workspace/kmalloctest/kmtest.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/fly/workspace/kmalloctest/kmtest.mod.o
LD [M] /home/fly/workspace/kmalloctest/kmtest.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.15.0-142-generic'
# ls
kmtest.c kmtest.ko kmtest.mod.c kmtest.mod.o kmtest.o Makefile modules.order Module.symvers
(2)insmod。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-414731.html
# insmod kmtest.ko
# dmesg -c
[160514.302923] 執(zhí)行:kmalloc(...)函數(shù)成功,地址 = 0xffff8f54b28ac000
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-414731.html
到了這里,關(guān)于Linux內(nèi)核模塊vmalloc和kmalloc系統(tǒng)調(diào)用的代碼實(shí)戰(zhàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!