我正在编写一个使用kmem_cache_create和kmem_cache_alloc在内核空间中创建堆栈的模块但是它不起作用。也许我已经用指针做了一些不好的事情,或者我没有理解slab分配的整个概念。我已经向同学和我的实验室负责人展示了代码,遗憾的是,任何人都无法帮助我。
这是我的代码在“堆栈”上分配5个结构
#include<linux/module.h>
#include<linux/slab.h>
#include<linux/string.h>
static struct example_struct {
unsigned int id;
char example_string[10];
struct example_struct *next;
} *example_struct_pointer;
static struct example_struct *top = NULL;
static struct kmem_cache *example_cachep;
static void example_constructor(void *argument)
{
static unsigned int id;
static char test_string[] = "Stack";
struct example_struct *example = (struct example_struct *)argument;
example->id = id;
strcpy(example->example_string,test_string);
example->next = top;
top = example;
id++;
}
void print_example_struct(struct example_struct *example)
{
pr_notice("Struct id: %u\n",example->id);
pr_notice("String field content: %s\n",example->example_string);
}
static int __init slabmod_init(void)
{
example_cachep = kmem_cache_create("example cache", sizeof(struct example_struct),0, SLAB_HWCACHE_ALIGN|SLAB_POISON|SLAB_RED_ZONE, example_constructor);
if(IS_ERR(example_cachep)) {
pr_alert("Error creating cache: %ld\n",PTR_ERR(example_cachep));
return -ENOMEM;
}
for(i=1 ; i<6 ; i++)
{
printk(KERN_ALERT "i: %d\n",i);
example_struct_pointer = (struct example_struct *) kmem_cache_alloc(example_cachep,GFP_KERNEL);
if(IS_ERR(example_struct_pointer)) {
pr_alert("Error allocating from cache: %ld\n", PTR_ERR(example_struct_pointer));
kmem_cache_destroy(example_cachep);
return -ENOMEM;
}
}
return 0;
}
static void __exit slabmod_exit(void)
{
struct example_struct *tmp = example_struct_pointer;
if(example_cachep) {
while(example_struct_pointer != NULL) {
print_example_struct(example_struct_pointer);
tmp = example_struct_pointer;
example_struct_pointer = tmp->next;
kmem_cache_free(example_cachep,tmp);
}
kmem_cache_destroy(example_cachep);
}
}
module_init(slabmod_init);
module_exit(slabmod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("kostek888888");
MODULE_DESCRIPTION("A module demonstrating use of the slab allocator.");
MODULE_VERSION("1.0");
我也有这段代码的调试版本:
#include<linux/module.h>
#include<linux/slab.h>
#include<linux/string.h>
static struct example_struct {
unsigned int id;
char example_string[10];
struct example_struct *next;
} *example_struct_pointer;
static struct example_struct *top = NULL;
static struct kmem_cache *example_cachep;
static unsigned int i;
static void example_constructor(void *argument)
{
static unsigned int id;
static char test_string[] = "Stack";
struct example_struct *example = (struct example_struct *)argument;
example->id = id;
strcpy(example->example_string,test_string);
example->next = top;
top = example;
id++;
}
void print_example_struct(struct example_struct *example)
{
pr_notice("Struct id: %u\n",example->id);
//pr_notice("String field content: %s\n",example->example_string);
printk(KERN_ALERT "example_struct_pointer: %p\n",example_struct_pointer);
//printk(KERN_ALERT "top: %p\n",top);
printk(KERN_ALERT "i: %d\n",i);
i++;
}
static int __init slabmod_init(void)
{
example_cachep = kmem_cache_create("example cache", sizeof(struct example_struct),0, SLAB_HWCACHE_ALIGN|SLAB_POISON|SLAB_RED_ZONE, example_constructor);
if(IS_ERR(example_cachep)) {
pr_alert("Error creating cache: %ld\n",PTR_ERR(example_cachep));
return -ENOMEM;
}
for(i=1 ; i<6 ; i++)
{
printk(KERN_ALERT "i: %d\n",i);
example_struct_pointer = (struct example_struct *) kmem_cache_alloc(example_cachep,GFP_KERNEL);
if(IS_ERR(example_struct_pointer)) {
pr_alert("Error allocating from cache: %ld\n", PTR_ERR(example_struct_pointer));
kmem_cache_destroy(example_cachep);
return -ENOMEM;
}
}
return 0;
}
static void __exit slabmod_exit(void)
{
struct example_struct *tmp = example_struct_pointer;
i = 1;
if(example_cachep) {
while(example_struct_pointer != NULL) {
print_example_struct(example_struct_pointer);
printk(KERN_ALERT "tmp: %p\n",tmp);
printk(KERN_ALERT "next: %p / %p\n\n",top->next,*(top->next));
tmp = example_struct_pointer;
example_struct_pointer = tmp->next;
kmem_cache_free(example_cachep,tmp);
}
printk(KERN_ALERT "tmp: %p\n",tmp);
printk(KERN_ALERT "next: %p\n\n",top->next);
printk(KERN_ALERT "example_struct_pointer: %p\n",example_struct_pointer);
kmem_cache_destroy(example_cachep);
}
}
module_init(slabmod_init);
module_exit(slabmod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("kostek888888");
MODULE_DESCRIPTION("A module demonstrating use of the slab allocator.");
MODULE_VERSION("1.0");
在输出中,当我只在范围1-5中执行5次kmem_cache_alloc时,我得到范围为0-11的12个元素,并且还显示消息“Slab cache仍然有对象”。
Here is screenshot demonstrating words above
之后我收到了Call Trace消息,因此内存错误。有时它会暂停整个虚拟机。
我在__exit的while循环中交换了指针,用于检查它将显示的内容 - 我有122个元素和相同的消息,所以这可能是一个整块(但可能因为消息而不完整?)。指针“next”在DEC中始终具有相同的值122 - 结构是122字节宽吗?结构尺寸给了我一些巨大的价值超过1,000,000%d。
原始代码,只分配一个结构,像魅力一样:
#include<linux/module.h>
#include<linux/slab.h>
#include<linux/string.h>
static struct example_struct {
unsigned int id;
char example_string[10];
} *example_struct_pointer;
static struct kmem_cache *example_cachep;
static void example_constructor(void *argument)
{
static unsigned int id;
static char test_string[] = "Test";
struct example_struct *example = (struct example_struct *)argument;
example->id = id;
strcpy(example->example_string,test_string);
id++;
}
void print_example_struct(struct example_struct *example)
{
pr_notice("Example struct id: %u\n",example->id);
pr_notice("Example string field content: %s\n",example->example_string);
}
static int __init slabmod_init(void)
{
example_cachep = kmem_cache_create("example cache", sizeof(struct example_struct),0, SLAB_HWCACHE_ALIGN|SLAB_POISON|SLAB_RED_ZONE, example_constructor);
if(IS_ERR(example_cachep)) {
pr_alert("Error creating cache: %ld\n",PTR_ERR(example_cachep));
return -ENOMEM;
}
example_struct_pointer = (struct example_struct *) kmem_cache_alloc(example_cachep,GFP_KERNEL);
if(IS_ERR(example_struct_pointer)) {
pr_alert("Error allocating form cache: %ld\n", PTR_ERR(example_struct_pointer));
kmem_cache_destroy(example_cachep);
return -ENOMEM;
}
return 0;
}
static void __exit slabmod_exit(void)
{
if(example_cachep) {
if(example_struct_pointer) {
print_example_struct(example_struct_pointer);
kmem_cache_free(example_cachep,example_struct_pointer);
}
kmem_cache_destroy(example_cachep);
}
}
module_init(slabmod_init);
module_exit(slabmod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arkadiusz Chrobot <***>");
MODULE_DESCRIPTION("A module demonstrating useing of the slab allocator.");
MODULE_VERSION("1.0");
我检查了像Linux设备驱动程序和类似的书籍 - 到处都是普通的功能,只有一个元素的例子。
我使用内核3.16.0-4-686-pae但在内核4.9中的情况是一样的。
我将对每一个回复表示感谢:)
答案 0 :(得分:1)
您错误假设每次调用 实际上,只有在分配器控制它之前,才会调用此回调函数以预先初始化“垃圾”内存。 按顺序: 回调函数在步骤1中仅称为 ONCE 。分配器假定在步骤2(释放) p <指向的对象/ em> 已处于初始化状态,因此步骤3不需要初始化。 使用ctor()
时kmem_cache_create()
(kmem_cache_create()
的最后一个参数)被称为。< / p>
kmem_cache_alloc()
,返回指针 p 。kmem_cache_free(p)
(假设分配器仍然控制 p )。kmem_cache_alloc()
,返回指针 p 。kmem_cache
的实施列表的正确方法是:static void example_constructor(void *argument)
{
static unsigned int id;
static char test_string[] = "Stack";
struct example_struct *example = (struct example_struct *)argument;
/*
* This only garantee that at any time every element in the stack has unique id.
* New element may have same id as previously deleted one.
*/
example->id = id;
// All elements will have given string.
strcpy(example->example_string,test_string);
// Appending into the stack cannot be performed in the constructor.
// example->next = top;
// top = example;
id++;
}
/* Push allocated element into the stack and return that element. */
struct example_struct* push(void)
{
struct example_struct* example = kmem_cache_alloc(example_cachep,GFP_KERNEL);
if(example) {
// Add to the stack here
example->next = top;
top = example;
}
return example;
}
/* Pop element from the stack and free the element. */
void pop(void)
{
// Take the first element.
struct example_struct *example = top;
// Remove the element from the stack
top = example->next;
// In given example re-initialization actions before freeing the element are not needed.
kmem_cache_free(example_cachep, example);
}
static int __init slabmod_init(void)
{
...
// Test the stack.
for(i=1 ; i<6 ; i++) {
printk(KERN_ALERT "i: %d\n",i);
example_struct_pointer = push();
if(!example_struct_pointer)) {
...
}
}
return 0;
}
static void __exit slabmod_exit(void)
{
...
// Clean the stack
while(top) pop();
...
}