2015-11-25 98 views
3

我在我的代碼中使用linux/list.h來實現隊列/堆棧行爲。在頭/尾添加API是如下:將項目添加到Linux內核鏈接列表

static inline void list_add(struct list_head *new, struct list_head *head) 
{ 
     __list_add(new, head, head->next); 
} 

類似的是list_add_tail。令人驚訝的是,它什麼也沒有返回(void),所以這意味着使用這個API在內核中添加列表總是成功的。我知道這裏沒有完整的概念,但如果新節點的內存分配不可用以及其他可能的原因是什麼?

+0

你也可以參考這個答案:http://stackoverflow.com/questions/33850930/correct-way-to-join-two-double-linked-list/ – 0andriy

回答

6

list API不會動態分配任何內存。我自己發現這件事有點令人費解。這裏的問題在於,Linux是用C編寫的,而不是C++,但是它以一種完全面向對象的方式實現了事物,但是在C中它看起來像是從頭到尾。它的工作原理如下(這也適用於其他幾個Linux API,例如kobj):

您定義了一些struct,它應該是列表的成員。與通常想象鏈接列表的方式相反,通過分配一些不透明的列表項並將指針指向實際對象,該對象將不會被放入列表中,您使成爲您的struct的實際成員

struct something { 
    struct list_head list; 
    uint8_t some_datum; 
    uint16_t some_other_datum; 
    void *a_pointer; 
}; 

你的列表會出現一些獨立struct list_head

static LIST_HEAD(list_of_somethings); 

將元素添加到list_of_somethings你現在會做類似

struct something *s = kmalloc(sizeof(*s), GFP_KERNEL); 
s->some_datum = 23; 
s->some_other_datum = 0xdeadbeef; 
s->a_pointer = current; 
list_add(&s->list, &list_of_somethings); 

換句話說,你已經分配了元素。這看起來完全不可思議,但像f * ck一樣優雅。這種「設計模式」允許在C中有不透明類型的列表,這在以另一種方式做起來並不容易:列表本身就是一堆指向對方的列表。正如你知道實際的struct你expeting作爲一個程序員,你知道這個struct的元素是實際list_head並且可以使用container_of宏得到的指針,你把名單最終struct

struct list_head *p = &list_of_somethings.next; 
struct something *s = container_of(p, struct something, list); 
pr_notice("some data = %i\n", s->some_data); 

注意,表示該清單自身的實際struct list_head<linux/list.h>定義的迭代宏特殊處理,即

#define list_for_each(pos, head) \ 
     for (pos = (head)->next; pos != (head); pos = pos->next) 

list_of_somethings地址將被用於阻止我是否迭代到達列表的末尾(或者實際上是列表對象)。 這也是爲什麼空列表被定義爲具有nextprev指向struct list_head本身的原因。

我也需要一些時間來包裹我的頭。 ;)

+0

感謝安德烈亞斯的詳細解釋。我完全錯過了我已經分配了包含list_head的節點的這一點。無論如何,你的回答給了我更多的信息。 –

1

看起來好像所有的內存已經被你分配了,所以它所做的只是連接已經分配的指針。

內存已經存在,它所做的只是填充它,所以沒有任何真正的方式可以失敗。

+0

謝謝科林。我完全錯過了這一點。 –