68 {
69 __list_add(new, head, head->next);
70 }
84 static inline void list_add_tail(struct list_head *new, struct list_head *head)
85 {
86 __list_add(new, head ->prev, head);

87 }
其中,list_add()将数据插入在head之后,list_add_tail()将数据插入在head->prev之后。其实对于循环链表来说,表头的next、prev分别指向链表中的第一个和最后一个节点,所以,list_add()和list_add_tail()的区别并不大。
(4)删除。
搞懂谭浩强那本书之后看这些链表的代码那就是小菜一碟。再来看下一个 list_del_init(),里的元素不能只加不减,没用了的元素就该删除掉,把空间腾出来给别人。郭敬明说过,我生命里的温暖就那么多,我全部给了你,但是你离开了我,你叫我以后怎么再对别人笑……
链表里的元素不能只加不减,没用了的元素就应该删除掉。for循环 链表
254 static inline void list_del_init(struct list_head *entry)
255 {
256 __list_del(entry->prev, entry->next);
257 INIT_LIST_HEAD(entry);
258 }
list_del_init()从链表里删除一个元素,并且将其初始化。
(5)遍历。
内核中的链表仅仅保存了list_head结构的地址,我们如何通过它或取一个链表节点真正的数据项?这就要提到有关链表的所有操作里面,最为重要超级经典的list_entry宏了,我们可以通过它很容易地获得一个链表节点的数据。
425 #define list_entry(ptr, type, member) /
426 container_of(ptr, type, member)
我相信,list_entry()这个宏在Linux内核代码中的地位,就相当于广告词中的任静付笛生的洗洗更健康,相当于大美女关之琳的一分钟轻松做女人,这都是耳熟能详妇孺皆知的,是经典中的经典。如果你说你不知道list_entry(),那你千万别跟人说你懂Linux内核,就好比你不知道陈文登不知道任汝芬你就根本不好意思跟人说你考过研,要知道每个考研人都是左手一本陈文登右手一本任汝芬。
可惜,关于list_entry,这个谭浩强老师的书里就没有了,当然你不能指责谭浩强的书不行,再好的书也不可能包罗万象。
关于list_entry(),让我们结合实例来看,还是hub驱动的那个例子,当我们真的要处理hub的事件的时候,我们当然需要知道具体是哪个hub触发了这起事件。而list_entry的作用就是,从struct list_head event_list得到它所对应的struct usb_hub结构体变量。for循环 链表比如以下四行代码:
struct list_head *tmp;
struct usb_hub *hub;
tmp = hub_event_list.next;
hub = list_entry(tmp, struct usb_hub, event_list);
从全局链表hub_event_list中取出一个来,叫做tmp,然后通过tmp,获得它所对应的struct usb_hub。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-78237-2.html
中国一方面派军舰
你还涨工资
防空