Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在linux内核中为struct数组分配内存,并获得奇怪的输出od structs id_C_Linux_Struct_Kernel - Fatal编程技术网

在linux内核中为struct数组分配内存,并获得奇怪的输出od structs id

在linux内核中为struct数组分配内存,并获得奇怪的输出od structs id,c,linux,struct,kernel,C,Linux,Struct,Kernel,我在linux内核中编写了一个程序,它应该为5个简单的结构分配内存,每个结构都有唯一的id,所以我在构造函数中使用static int并增加它,最后我只是将消息打印到缓冲区。当我看到缓冲区时,我得到了一个奇怪的结果,因为id的值,比如0、64、128、192、256,我很惊讶,因为我认为我会看到0、1、2、3、4这样的值。为什么我会得到这样的结果?有什么不对劲吗 输出: [2653.505140]示例结构id:0 [2653.505143]示例字符串字段内容:测试 [2653.526565]示例

我在linux内核中编写了一个程序,它应该为5个简单的结构分配内存,每个结构都有唯一的id,所以我在构造函数中使用static int并增加它,最后我只是将消息打印到缓冲区。当我看到缓冲区时,我得到了一个奇怪的结果,因为id的值,比如0、64、128、192、256,我很惊讶,因为我认为我会看到0、1、2、3、4这样的值。为什么我会得到这样的结果?有什么不对劲吗

输出:

[2653.505140]示例结构id:0
[2653.505143]示例字符串字段内容:测试
[2653.526565]示例结构id:64
[2653.526568]示例字符串字段内容:测试
[2653.526623]示例结构id:128
[2653.526625]示例字符串字段内容:测试
[2653.550439]示例结构id:192
[2653.550443]示例字符串字段内容:测试
[2653.550513]示例结构id:256
[2653.550514]示例字符串字段内容:测试

这是我的代码:

#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[5];

static struct kmem_cache *example_cachep[5];

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: %d\n",example->id);
    pr_notice("Example string field content: %s\n",example->example_string);
}

static int __init zad1_init(void)
{
    int i;
    for(i = 0; i < 5; i++){
        example_cachep[i] = 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[i])) {
            pr_alert("Error creating cache: %ld\n",PTR_ERR(example_cachep[i]));
            return -ENOMEM;
        }
    }

    for(i = 0; i < 5; i++){
        example_struct_pointer[i] = (struct example_struct *) kmem_cache_alloc(example_cachep[i],GFP_KERNEL);
        if(IS_ERR(example_struct_pointer[i])) {
            pr_alert("Error allocating form cache: %ld\n", PTR_ERR(example_struct_pointer[i]));
            kmem_cache_destroy(example_cachep[i]);
            return -ENOMEM;
        }
    }
    
    return 0;
}

static void __exit zad1_exit(void)
{
    int i;
    for(i = 0; i < 5; i++){
        if(example_cachep[i]) {
            if(example_struct_pointer[i]) {
                print_example_struct(example_struct_pointer[i]);
                kmem_cache_free(example_cachep[i],example_struct_pointer[i]);
            }
            kmem_cache_destroy(example_cachep[i]);
        }
    }
}

module_init(zad1_init);
module_exit(zad1_exit);

MODULE_LICENSE("GPL");
#包括
#包括
#包括
静态结构示例\u结构{
无符号整数id;
字符示例_字符串[10];
}*示例_结构_指针[5];
静态结构kmem_cache*示例_cachep[5];
静态void示例_构造函数(void*参数)
{
静态无符号整数id;
静态字符测试_字符串[]=“测试”;
struct example_struct*example=(struct example_struct*)参数;
示例->id=id;
strcpy(示例->示例字符串、测试字符串);
id++;
}
无效打印\u示例\u结构(结构示例\u结构*示例)
{
pr_通知(“示例结构id:%d\n”,示例->id);
请购单通知(“示例字符串字段内容:%s\n”,示例->示例字符串);
}
静态整数初始化zad1初始化(无效)
{
int i;
对于(i=0;i<5;i++){
示例缓存p[i]=kmem\u缓存创建(“示例缓存”,sizeof(struct example\u struct),0,SLAB\HWCACHE\u ALIGN,SLAB\u毒物,SLAB\u红色区域,示例构造函数);
if(IS_ERR(例如_cachep[i])){
pr_警报(“创建缓存时出错:%ld\n”,PTR_ERR(例如缓存[i]));
return-ENOMEM;
}
}
对于(i=0;i<5;i++){
示例\u结构\u指针[i]=(结构示例\u结构*)kmem\u cache\u alloc(示例\u cachep[i],GFP\u内核);
if(IS_ERR(例如结构指针[i])){
pr_警报(“分配表单缓存时出错:%ld\n”,PTR_ERR(示例结构指针[i]);
kmem_cache_destroy(示例_cachep[i]);
return-ENOMEM;
}
}
返回0;
}
静态无效\uuuu出口zad1\u出口(无效)
{
int i;
对于(i=0;i<5;i++){
if(示例_cachep[i]){
if(示例\u结构\u指针[i]){
打印示例结构(示例结构指针[i]);
kmem_cache_free(示例_cachep[i],示例_struct_pointer[i]);
}
kmem_cache_destroy(示例_cachep[i]);
}
}
}
模块初始化(zad1初始化);
模块出口(zad1出口);
模块许可证(“GPL”);

ctor
函数的
kmem\u cache\u create
参数不是一般意义上的构造函数

不能保证给定的函数只会被调用一次,并且只有在从缓存请求对象时才会被调用。担保实际上是相反的():

因此,对
ctor
的调用可能比从缓存请求的对象数量多得多

如果只想分配和初始化几个对象,只需定义相应的构造函数:

// Single cache can be used for allocate multiple object.
// No needs to define a cache-per-object.
static struct kmem_cache* example_cachep;

// Constructor for the object of type 'example_struct'.
static struct example_struct* create_example_object(void)
{
    static unsigned int id;
    struct example_struct *example = kmem_cache_alloc(example_cachep, GFP_KERNEL);
    if (example != NULL)
    {
      example->id = id;
      strcpy(example->example_string, "Test");
      id++;
    }

    return example;
}

static int __init zad1_init(void)
{
  // ...
  // Create the cache.
  example_cachep = kmem_cache_create("example cache", sizeof(struct example_struct),0, SLAB_HWCACHE_ALIGN|SLAB_POISON|SLAB_RED_ZONE, example_constructor);

  // create several 'example' objects.
  for(i = 0; i < 5; i++){
    example_struct_pointer[i] = create_example_object();
    if(example_struct_pointer[i] == NULL)
    {
       // ... Somehow process the allocation failure.
    }
  }

  return 0;
}
//单个缓存可用于分配多个对象。
//无需为每个对象定义缓存。
静态结构kmem_cache*示例_cachep;
//类型为“example_struct”的对象的构造函数。
静态结构示例\u结构*创建\u示例\u对象(无效)
{
静态无符号整数id;
struct example\u struct*example=kmem\u cache\u alloc(example\u cachep,GFP\u内核);
如果(示例!=NULL)
{
示例->id=id;
strcpy(示例->示例字符串,“测试”);
id++;
}
返回示例;
}
静态整数初始化zad1初始化(无效)
{
// ...
//创建缓存。
示例_cachep=kmem_cache_create(“示例缓存”,sizeof(struct example_struct),0,SLAB_HWCACHE_ALIGN | SLAB_POISON | SLAB_RED_ZONE,示例_构造函数);
//创建几个“示例”对象。
对于(i=0;i<5;i++){
示例_结构_指针[i]=创建_示例_对象();
if(示例结构指针[i]==NULL)
{
//…以某种方式处理分配失败。
}
}
返回0;
}


ctor
参数仅用于初始化对象的某些字段。这样的初始化可以节省一点时间(稍微提高性能),但只有在以下两种条件都适用时才能

  • 您可以主动地从缓存中创建(分配+初始化)和销毁(取消分配)对象
  • 要初始化的字段在刚刚初始化的对象和要解除分配的对象中具有完全相同的值
  • 例如,在对象中可以有一个
    usage\u count
    字段,该字段在对象刚刚初始化和对象将被释放时都等于0

    ctor
    对于此类字段的用处在于,对于先前从同一缓存中解除分配的已分配对象,可能不会调用
    ctor
    。也就是说,您可以通过不初始化已经具有所需值的字段来节省时间


    因为不初始化单个(或多个)值只能节省一点时间,但是调用
    ctor
    的次数可能会超过需要的次数,因此您应该仔细测量您是否确实获得了性能,而不是失去了性能。

    您误解了
    kmem\u缓存
    函数的工作原理。
    kmem\u cache\u create
    功能
    // Single cache can be used for allocate multiple object.
    // No needs to define a cache-per-object.
    static struct kmem_cache* example_cachep;
    
    // Constructor for the object of type 'example_struct'.
    static struct example_struct* create_example_object(void)
    {
        static unsigned int id;
        struct example_struct *example = kmem_cache_alloc(example_cachep, GFP_KERNEL);
        if (example != NULL)
        {
          example->id = id;
          strcpy(example->example_string, "Test");
          id++;
        }
    
        return example;
    }
    
    static int __init zad1_init(void)
    {
      // ...
      // Create the cache.
      example_cachep = kmem_cache_create("example cache", sizeof(struct example_struct),0, SLAB_HWCACHE_ALIGN|SLAB_POISON|SLAB_RED_ZONE, example_constructor);
    
      // create several 'example' objects.
      for(i = 0; i < 5; i++){
        example_struct_pointer[i] = create_example_object();
        if(example_struct_pointer[i] == NULL)
        {
           // ... Somehow process the allocation failure.
        }
      }
    
      return 0;
    }