2017-10-20 65 views
1

来自指南Understanding The Linux Kernel, 3rd Edition,章节8.2.12。分配板对象,存在下面的代码段:Linux中的指针计算内核分配实现

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一个指针,它包含下列字段(按此次序) -

[类型]无符号整型

[名称]利用

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

[类型]无符号整型

[名称]限制

本地高速缓存即是

[描述]大小,在本地缓存中的指针的最大数量。

[类型]无符号整型

[名称] batch_count

[描述]块大小为本地高速缓存再填充或排空。

【类型】无符号整型

[名]感动

[说明]标志设置为1,如果本地缓存最近已被使用。

所以ac+1将指向到avail值(或在相反的情况下,尾段第3字节)的第二个字节,这使得没有任何意义。

我得到这个错误的方式?

回答

3

是的,你错了。

指针算术是根据指向的类型而不是字节。

考虑一下:

int a[2], *p = a; 

++p; 

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

请记住,数组索引是通过指针运算来工作的,所以它也必须是这个原因。

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

+0

你能否提供更常见的用法和这种编码的例子?我会期望使用另一个封装这些数据的结构体,而这个封装体结构体将有一个指向另一个结构体的指针的字段,另一个指向其他数据的字段。这种方式干净清晰。为什么要使用这种代码到底有什么好处呢? – user2162550