2017-10-20 88 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