对于双向链表就是在单向链表的基础上加了一个向前的结构体指针。对于一些操作的思想更加的简单。麻烦的事情就是要判断的内容更多了。因为内核链表中运用到的都是双向链表。所以要学习内核链表。就先要会对双向链表进行基本的操作。比如新增和显示。
内核链表中的实现思想类似与面向对象的思想,成员和方法分开写。比如下面这个简单的代码:
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