struct list_head { struct list_head *next, *prev; }; list_add_tail(&buf->vb.queue, &vid->active); /** * list_add_tail - add a new entry * @new: new entry to be added * @head: list head to add it before * * Insert a new entry before the specified head. * This is useful for implementing queues. */ static __inline__ void list_add_tail(struct list_head *_new, struct list_head *head) { __list_add(_new, head->prev, head); } /* * Insert a new entry between two known consecutive entries. * * This is only for internal list manipulation where we know * the prev/next entries already! */ static __inline__ void __list_add(struct list_head * _new, struct list_head * prev, struct list_head * next) { next->prev = _new; _new->next = next; _new->prev = prev; prev->next = _new; }
很多地方說:這個函數完成的功能就是添加一個新的結點在head的左邊,其實不然,它是從右向左在head->priv和head兩個節點之間插入_new。
假設剛開始建立鏈表,只有struct list_head *head,
那么前兩句話有用:將next->prev = _new;
_new->next = next;
這就是將new節點添加到head 節點的左邊,那么接 下來兩句沒用: _new->prev = prev; prev->next = _new;
如果head左邊已近有了其他節點,那么調用list_add_tail()函數后,前邊兩句的功能一樣,都是把新的節點添加在head左邊,而后兩句就是把新節點添加在原來head之前節點(head->priv)右邊,這樣就串起來了。
那list_add就反過來,把新的節點添加在head和head之后的節點(head->next)之間;
關於list_add和list_add_tail建立棧和FIFO:
list_add和list_add_tail都是在head兩邊插入新的節點,所以list_add先插入的節點向右移,head->next是最后插入的節點,list_add_tail先插入的節點向左移,head->next是最先插入的節點;
遍歷鏈表都是從head開始向下,所以用list_add建立的鏈表先訪問的是最后插入的節點,類似於棧;list_add_tail建立的鏈表先訪問的是最先插入的節地點,類似於FIFO。