从指南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个字节),这根本没有意义。
我得错了吗?
答案 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
的指针,就像您显示的代码一样。