Linux内核分配实现中的指针计算

时间:2017-10-20 09:47:27

标签: c linux pointers caching

从指南Understanding The Linux Kernel, 3rd Edition 8.2.12章节。分配一个Slab对象,有以下代码:

void * kmem_cache_alloc(kmem_cache_t *cachep, int flags)
{  
    unsigned long save_flags;  
    void *objp;  
    struct array_cache *ac;  
    local_irq_save(save_flags);  
    ac = cache_p->array[smp_processor_id()];  
    if (ac->avail) 
    {  
       ac->touched = 1;
       objp = ((void**)(ac+1))[--ac->avail];  
    } else  
        objp = cache_alloc_refill(cachep, flags);  
    local_irq_restore(save_flags);  return objp; 
}

现在,根据指南查看行((void**)(ac+1))[--ac->avail]

  

因为本地缓存数组存储在ac描述符之后,   ((void **)(ac + 1))[ - ac-> avail]获取该自由对象的地址   降低ac-> avail的值。

但是,因为ac是指向struct array_cache类型的指针,其中包含以下字段(按此顺序) -

  

[type] unsigned int

     

[name] avail

     

[description]本地缓存中可用对象的指针数。    该字段还充当缓存中第一个空闲槽的索引。

     

[type] unsigned int

     

[姓名]限制

     

[description]本地缓存的大小,即本地缓存中的最大指针数。

     

[type] unsigned int

     

[name] batch_count

     

[description]本地缓存重填或清空的块大小。

     

[type] unsigned int

     

[姓名]触及了

     

[description]如果最近使用了本地缓存,则标志设置为1.

所以ac+1将指向avail值的第二个字节(或相反Endian情况下的第3个字节),这根本没有意义。

我得错了吗?

1 个答案:

答案 0 :(得分:3)

是的,你错了。

指针算法是指向的类型,而不是字节。

考虑一下:

int a[2], *p = a;

++p;

这使p等于&a[1],而不是((char *) &a[0]) + 1。因此,该增量将使实际指针值增加sizeof *p,即sizeof (int)

请记住,数组索引通过指针算法工作,因此也必须采用这种方式。

在C中实现各种数据结构时,你有一个以某个struct的实例开头的内存块,然后是其他数据(通常由{中的字段描述)很常见{1}})。然后,该数据的第一个字节位于struct,假设sp + 1是指向sp的指针,就像您显示的代码一样。