第十八天:双向链表与内核链表

  对于双向链表就是在单向链表的基础上加了一个向前的结构体指针。对于一些操作的思想更加的简单。麻烦的事情就是要判断的内容更多了。因为内核链表中运用到的都是双向链表。所以要学习内核链表。就先要会对双向链表进行基本的操作。比如新增和显示。

    内核链表中的实现思想类似与面向对象的思想,成员和方法分开写。比如下面这个简单的代码:

 1 #include<stdio.h>
 2
 3 struct boy;
 4 struct file_operations;
 5
 6 struct boy{
 7     int age;//成员
 8     char *gf;
 9     struct file_operations *ops;
10 };
11 struct file_operations{ //方法
12     void (*fp)(struct boy *);
13 };
14 void eat(struct boy *t)//t 为this指针
15 {
16     printf("please %s\n",t->gf);
17 }
18 int main()
19 {
20     struct file_operations file;
21     file.fp = eat;
22
23     struct boy tom;
24     tom.gf = "lily";
25     tom.ops = &file;
26     tom.ops->fp(&tom);
27
28     struct boy jim;
29     jim.gf = "lucy";
30     jim.ops = &file;
31     jim.ops->fp(&jim);
32 }

在这个函数中,定义了两个结构体,boy和file_operations ,在file_operations结构体中定义了函数指针,boy的结构体中定义了file_operations结构体。这样做,boy的成员就能过通过函数指针来访问函数。

   下面的代码是今晚最终的作业,对内核链表进行排序。这个就是对前面知识的大综合了。没有什么新的内容。

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #define container_of(ptr,type,mem) (type*)((unsigned long)ptr - (unsigned long)&((type *)0)->mem)
  4
  5 struct list_head{
  6     struct list_head *pre;
  7     struct list_head *next;
  8 };
  9 struct person{
 10     struct list_head li;
 11     int age;
 12 };
 13 struct list_head *insert(struct list_head * head ,int age);
 14 void show(struct list_head  *head);
 15 void show_pre(struct list_head *head);
 16 struct list_head *sort(struct list_head *head);
 17 int main()
 18 {
 19     struct list_head  *head = NULL;
 20     head = insert(head,10);
 21     head = insert(head,12);
 22     head = insert(head,13);
 23     head = insert(head,19);
 24     head = insert(head,21);
 25     head = insert(head,20);
 26     show(head);
 27     printf("---------\n");
 28     show_pre(head);
 29     printf("---------\n");
 30     head = sort(head);
 31     show(head);
 32 }
 33 struct list_head *insert(struct list_head * head ,int age){
 34
 35     struct  person * p = (struct person *)malloc(sizeof(struct person));
 36     p->age = age;
 37     if(head == NULL){
 38         p->li.pre = NULL;
 39         p->li.next = NULL;
 40     }else{
 41         p->li.pre  = NULL;
 42         p->li.next = head;
 43         head->pre  = &p->li;
 44     }
 45     return &p->li ;
 46 }
 47
 48 void show(struct list_head  *head){
 49     struct person *tmp;
 50     while(head){
 51         tmp = container_of(head,struct person,li);
 52         printf("age is %d\n",tmp->age);
 53         head = head ->next;
 54     }
 55 }
 56 void show_pre(struct list_head *head){
 57     if(head ==NULL)
 58         return ;
 59     struct list_head *tail = head;
 60     while(tail->next)
 61         tail = tail ->next;
 62     struct person *tmp;
 63     while(tail){
 64         tmp = container_of(tail,struct person,li);
 65         printf("age is %d\n",tmp->age);
 66         tail = tail->pre;
 67     }
 68 }
 69 struct list_head *sort(struct list_head *head){
 70
 71     if(head == NULL||head->next == NULL)
 72         return head;
 73     struct list_head *min = NULL;
 74     struct list_head *oldhead = head;
 75     struct list_head *newhead = NULL;
 76     struct list_head *cur =NULL ;
 77     struct list_head *tmp =NULL;
 78     struct list_head *tail =NULL;
 79     struct person *minvalue;
 80     struct person *curvalue;
 81     while(oldhead){
 82         //找到最小的
 83         min = oldhead;
 84         cur = oldhead;
 85         tail = oldhead;
 86         while(cur){
 87             minvalue = container_of(min,struct person,li);
 88             curvalue = container_of(cur,struct person,li);
 89             if(minvalue->age > curvalue->age){
 90                 min = cur;
 91             }
 92             cur = cur->next;
 93         }
 94         //切下 分成四种情况
 95         while(tail->next)
 96             tail = tail->next;
 97         if(oldhead ->next == NULL){
 98             oldhead = oldhead ->next;
 99         }else if(min == oldhead){
100             min->next->pre = NULL;
101             oldhead = oldhead ->next;
102         }else if(min == tail){
103             min->pre->next = NULL;
104
105         }else{
106             min->pre->next = min->next;
107             min->next->pre = min->pre;
108             min->pre = NULL;
109         }
110         min->next = NULL;
111         //链接到新的链表中
112         if(newhead ==NULL){
113             newhead = min;
114             tmp = newhead;
115         }else{
116             tmp ->next = min;
117             min ->next = NULL;
118             min->pre = tmp;
119             tmp = tmp->next;
120         }
121     }
122     return newhead;
123 }

  发现代码越写越长了。这个代码就是内核链表的实现。内核里面的链表结构大概如此。自己实现一遍后,对于以后的内核源码阅读会很有帮助。

 这个代码就是将container_of宏和双链表的操作结合起来了。综合性比较强。

时间: 2024-09-29 05:27:15

第十八天:双向链表与内核链表的相关文章

例说Linux内核链表(二)

链表使用 我认为熟悉内核链表功能最好的方法就是看一些简单的实例,实例是一个非常好的素材去更好的理解链表. 下面是一个例子,包含创建,添加,删除和遍历链表. <span style="font-size:14px;"><span style="color:#330099;">#include <stdio.h> #include <stdlib.h> #include "list.h" struct

例说Linux内核链表(三)

经常使用的linux内核双向链表API介绍 linux link list结构图例如以下: 内核双向链表的在linux内核中的位置:/include/linux/list.h 使用双向链表的过程,主要过程包括创建包括struct link_head结构的结构体(item),建立链表头.向链表中加入item(自己定义数据结构.双向链表数据单元).删除链表节点.遍历链表,判空等. 1.建立自己定义链表数据结构 struct kool_list{ int to; struct list_head li

Linux内核链表深度分析【转】

本文转载自:http://blog.csdn.net/coding__madman/article/details/51325646 链表简介: 链表是一种常用的数据结构,它通过指针将一系列数据节点连接成一条数据链.相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位置实时插入或者删除数据.链表的开销主要是访问的顺序性和组织链的空间损失. 内核链表的好主要体现为两点,1是可扩展性,2是封装.可扩展性肯定是必须的,内核一直都是在发展中的,所

Linux 内核 链表 的简单模拟

第零章:扯扯淡 出一个有意思的题目:用一个宏定义FIND求一个结构体struct里某个变量相对struc的编移量,如 struct student { int a; //FIND(struct student,a) 等于0 char b; //FIND(struct student,b)等于4 double c; }; 参考答案:#define FIND(type,member) ((size_t)&((type*)0)->member) 我这样理解(可能不太正确): (type*)0,0在

喜羊羊系列之数据结构内核链表

博客地址:http://blog.csdn.net/muyang_ren 内核链表示意图 关于内核链表与简单的双向连表,是否有过疑惑 内核链表定义: struct list_head{ struct list_head *next,*prev; }; struct doublelist{ datatype data; struct list_head list; }double_list; 简单的双向链表定义: struct doublelist{ datatype data; struct d

Linux内核链表深度分析

链表简介: 链表是一种常用的数据结构,它通过指针将一系列数据节点连接成一条数据链.相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位置实时插入或者删除数据.链表的开销主要是访问的顺序性和组织链的空间损失. 内核链表的好主要体现为两点,1是可扩展性,2是封装.可扩展性肯定是必须的,内核一直都是在发展中的,所以代码都不能写成死代码,要方便修改和追加.将链表常见的操作都进行封装,使用者只关注接口,不需关注实现.分析内核中的链表我们 可以做些什

第四季-专题7-Linux内核链表

专题7-Linux内核链表 1.链表简介 链表是一种常用的数据结构,它通过指针将一系列数据节点连接成一条数据链.相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位置实时插入或删除数据.链表的开销主要是访问的顺序性和组织链的空间损失. 传统链表与Linux内核链表的区别: 以前我们学习的链表主要有,单项链表.双向链表.双向循环链表.我们用的Linux内核链表示双向循环链表.Linux内核链表创建的目的就是,使用链表是统一操作和统一的函数.

Linux 内核链表

一 . Linux内核链表 1 . 内核链表函数 1.INIT_LIST_HEAD:创建链表 2.list_add:在链表头插入节点 3.list_add_tail:在链表尾插入节点 4.list_del:删除节点 5.list_entry:取出节点 6.list_for_each:遍历链表 2.程序代码

Linux 内核 链表 的简单模拟(2)

接上一篇Linux 内核 链表 的简单模拟(1) 第五章:Linux内核链表的遍历 /** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. */ #define list_for_each(pos, head) for (pos = (head)->next; pos != (head);