list.h分析
来源:互联网 发布:linux新建文件命令 编辑:程序博客网 时间:2024/04/30 08:58
6.链表的修改: 上面的函数调用了第一个函数,最后调用了初始化函数,让不用的结点指向自己,是安全的删除。
第一个函数调用的是list_add_tail(list,head),第二个函数调用的是list_add_tail(list,head),这两个函数的区别我就不细说了,前面提到过。
这个函数首先列举出来的这段代码和上面的每一个功能的第一个函数一样,都是被后面的函数调用的。先看它的参数,list是一个头结点,要把它后面的那一串链表插入到别的链表中,prev和next就是链表要插入的位置的前后结点,在函数体中,先用first和last记录这串要插入的链表的头和尾,把first和要插入位置的前面prev相连,把last和要插入位置的后面next相连,就像插入一个大结点一样把链表插入到规定位置。 第一个函数是把链表插入到head之后,head->next之前,就是说把链表插到头结点后,类似于头插法,第二个函数是把链表插入到head->prev之后,head之前,就是说把链表插到链表的最后,类似于尾插法。当然,在插入链表之前,要保证待插的那个链表不是空链表。最后一步初始化的作用就是释放了不用的那个链表头。
调用的切割函数如下:10.测试函数 11.判空函数 第二个比第一个函数“仔细”在哪里?前者只是认为只要一个结点的next指针指向头指针就算为空,但是后者还要去检查头节点的prev指针是否也指向头结点。另外,这种仔细也是有条件的,只有在删除节点时用list_del_init(),才能确保检测成功。
其实内核差不多都是把这些函数封装起来了,其实链表的修改也是这样的,代码其实很简单,没有什么解释的,就是把旧的结点的next和prev与原链表断开,再与新的结点的next和prev连接起来。如下函数:
- static inline void list_replace(struct list_head*new,struct list_head*old)
- {
- new->next=old->next;
- new->next->prev=new;
- new->prev=old->prev;
- new->prev->next=new;
- }
- static inline void list_replace_init(struct list_head*new,struct list_head*old)
- {
- list_replace(new,old);
- INIT_LIST_HEAD(old);
- }
7.链表的移动
链表的移动就是将一个结点移动到另一个结点,内核实现这个功能使用的是先把要移动的位置上的结点分离出来,再将要移动的结点添加到head之后进去就OK了:
- static inline void list_move(struct list_head*list, struct list_head*head)
- {
- __list_del_entry(list);
- list_add(list, head);
- }
- static inline void list_move_tail(struct list_head*list,
- struct list_head *head)
- {
- __list_del_entry(list);
- list_add_tail(list, head);
- }
8.链表的合并
链表的合并也比较简单,先看一下具体的实现函数:
- static inline void __list_splice(const struct list_head*list,struct list_head*prev,struct list_head*next)
- {
- struct list_head *first = list->next;
- struct list_head *last = list->prev;
- first->prev= prev;
- prev->next= first;
- last->next= next;
- next->prev= last;
- }
后面调用这个函数的代码如下:
- static inline void list_splice_init(struct list_head*list,struct list_head*head)
- {
- if(!list_empty(list)){
- __list_splice(list,head,head->next);
- INIT_LIST_HEAD(list);
- }
- }
- static inline void list_splice_tail_init(struct list_head*list,struct list_head*head)
- {
- if(!list_empty(list)){
- __list_splice(list,head->prev,head);
- INIT_LIST_HEAD(list);
- }
- }
9.将链表一分为二
能将链表合并就能将其一分为二,这个函数是将head后至entry之间(包括entry)的所有结点都“切开”,让他们成为一个以list为头结点的新链表。我们先从宏观上看,如果head本身是一个空链表则失败;如果head是一个单结点链表而且entry所指的那个结点又不再这个链表中,也失败;当entry恰好就是头结点,那么直接初始化list,为什么?因为按照刚才所说的切割规则,从head后到entry前事实上就是空结点。如果上述条件都不符合,那就可以“切割”了。上述的条件如下函数所写:
- static inline void list_cut_position(struct list_head*list,
- struct list_head *head, struct list_head*entry)
- {
- if (list_empty(head))
- return;
- if (list_is_singular(head)&&
- (head->next!= entry && head != entry))
- return;
- if (entry== head)
- INIT_LIST_HEAD(list);
- else
- __list_cut_position(list, head, entry);
- }
- static inline void __list_splice(const struct list_head*list,
- struct list_head *prev,
- struct list_head *next)
- {
- struct list_head *first = list->next;
- struct list_head *last = list->prev;
- first->prev= prev;
- prev->next= first;
- last->next= next;
- next->prev= last;
- }
测试函数其实理解起来挺简单的,一看代码就能明白到底是要测试什么,如下代码就测试的就是list是否是最后一个结点:
- static inline int list_is_last(const struct list_head*list,
- const struct list_head *head)
- {
- return list->next== head;
- }
下面的函数是测试head链表是否只有一个结点:这个链表既不能是空而且head前后的两个结点都得是同一个结点。
- static inline int list_is_singular(const struct list_head*head)
- {
- return !list_empty(head)&& (head->next== head->prev);
- }
- static inline int list_empty(const struct list_head*head)
- {
- return head->next== head;
- }
- static inline int list_empty_careful(const struct list_head*head)
- {
- struct list_head *next= head->next;
- return (next== head)&& (next == head->prev);
- }
仔细去分析这些代码收获真的挺大的,建议大家都去好好的分析一下list.h,会对你有帮助的!
- list.h分析
- list.h分析使用
- linux list.h分析
- list.h头文件分析
- list.h头文件分析
- list.h链表分析
- 我的bsd-list.h分析
- 分析linux/list.h中的list_head结构
- linux内核list.h头文件分析
- Linux内核的List.h分析
- list.h linux内核链表分析
- linux内核list.h分析(一)
- linux内核list.h分析(二)
- STL源码分析(2) -- list.h分析(1)
- linux内核list.h头文件分析(七)——list.h应用
- list.h
- <list.h>
- list.h
- struts2中常用的常量介绍
- java千万级别数据生成文件思路和优化
- SRM 586 DIV2 500
- iOS 扁平化 UI 库 FlatUIKit
- struts2文件上传大小
- list.h分析
- easy 51 pro 2.0宇宙版成功编译.
- zoj 3432 Find the Lost Sock(解决时间超时问题)
- hdu 2023 求平均成绩
- Spring JdbcTemplate方法详解
- iOS开发:Toast for iPhone 实例分享
- NYOJ 45-棋盘覆盖:大数问题
- APUE读书笔记-第11章-线程
- hdu 4001 To Miss Our Children Time (DP)