来自指南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]
行:
Because the local cache array is stored right after the ac descriptor, ((void**)(ac+1))[--ac->avail] gets the address of that free object and decreases the value of ac->avail.
但是,由于 ac
是指向类型 struct array_cache
的指针,它包含以下字段(按此顺序)-
[type] unsigned int
[name] avail
[description] Number of pointers to available objects in the local cache. The field also acts as the index of the first free slot in the cache.
[type] unsigned int
[name] limit
[description] Size of the local cache that is, the maximum number of pointers in the local cache.
[type] unsigned int
[name] batch_count
[description] Chunk size for local cache refill or emptying.
[type] unsigned int
[name] touched
[description] Flag set to 1 if the local cache has been recently used.
所以 ac+1
将指向 avail
值的第二个字节(或相反的 Endian 情况下的第 3 个字节),这根本没有意义。
我是不是理解错了?
最佳答案
是的,你错了。
指针运算是根据所指向的类型,而不是字节。
考虑一下:
int a[2], *p = a;
++p;
这使得 p
等于 &a[1]
,而不是 ((char *) &a[0]) + 1
。因此,该增量会将实际指针值增加 sizeof *p
,即 sizeof (int)
。
请记住,数组索引是通过指针算法工作的,因此出于这个原因也必须采用这种方式。
在 C 中实现各种数据结构时,您有一 block 内存以某个 struct
的实例开始,然后是其他数据(通常由 中的字段描述)是很常见的>结构
)。该数据的第一个字节位于 sp + 1
,假设 sp
是指向 struct
的指针,就像您显示的代码一样。
关于c - Linux内核分配实现中的指针计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46846480/