和菜鸟一起学linux之双向链表list head的简单实例
来源:互联网 发布:牛牛软件图片 编辑:程序博客网 时间:2024/06/06 21:06
经常在linux内核中看到list head这个链表头,有时候看着也不是很懂,很早就打算拎出来好好理解理解了。这次趁着编写SDK后有点小空闲,就拿出来晒晒吧。
简单的链表实现
#include <stdio.h>#include <stdlib.h>#include <string.h>struct list_head{ struct list_head *next, *prev;}; #define INIT_LIST_HEAD(ptr) do{ \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ }while(0) #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) #define offsetof(TYPE, MEMBER) ((size_t)& ((TYPE *)0)->MEMBER) #define container_of(ptr, type, member) ({\ const typeof( ((type *)0)->member ) *__mptr = (ptr);\ (type*)((char *)__mptr - offsetof(type,member));}) #define list_entry(ptr, type, member) \ container_of(ptr, type, member) #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) static inline void __list_del(struct list_head * prev, struct list_head * next){ next->prev = prev; prev->next = next;} static inline void __list_del_entry(struct list_head *entry){ __list_del(entry->prev, entry->next);}static inline void list_del_init(struct list_head *entry){ __list_del_entry(entry); INIT_LIST_HEAD(entry);} static inline void __list_add(struct list_head *new1, struct list_head *prev, struct list_head *next){ next->prev = new1; new1->next = next; new1->prev = prev; prev->next = new1;} static inline void list_add(struct list_head *new1, struct list_head *head){ __list_add(new1, head, head->next);} struct person{ int age; int weight; struct list_head list; };int main(void){ struct person *tmp; struct list_head *pos, *n; int age_i, weight_j; struct person person_head; INIT_LIST_HEAD(&person_head.list); for(age_i = 10, weight_j = 35; age_i < 40; age_i += 5, weight_j +=5) { tmp = (struct person *)malloc(sizeof(struct person)); tmp->age = age_i; tmp->weight = weight_j; list_add(&(tmp->list), &person_head.list); } printf("\n"); printf("============ print the list =============\n"); list_for_each(pos, &person_head.list) { tmp = list_entry(pos, struct person, list); printf("age:%d, weight: %d \n", tmp->age, tmp->weight); } printf("\n"); printf("======== print list after delete a node which age is 15 =======\n"); list_for_each_safe(pos, n, &person_head.list) { tmp = list_entry(pos, struct person, list); if(tmp->age== 15) { list_del_init(pos); free(tmp); } } list_for_each(pos, &person_head.list) { tmp = list_entry(pos, struct person, list); printf("age:%d, weight:%d\n", tmp->age, tmp->weight); } return 0;}
下面还是分析下这个list head中的各个函数和宏定义吧。
1、 INIT_LIST_HEAD
这个就是初始化链表头了,指针都指向本身
2、 list_for_each
这个就是遍历了函数,看看函数原型就知道是for循环了。和一般的单链表的遍历没什么多大区别。
3、 container_of
这个在以前的blog中有写用法
4、 list_entry
这个就是上面的container_of了,具体的含义就是根据list这个链表头的指针得到整个定义的结构体的指针。
5、 list_for_each_safe
这个和list_for_each的功能其实是一样的,只是他多了一个n中间变量,因为可以pos这个指针被删除了,pos的指向就会变了,而引入了n这个变量,那么就不会出错了,就安全了。所以这里多了一个safe。
6、 list_del_init
删除一个节点
7、 list_add
插入一个节点
函数主要的功能也讲完了,实现方法也可以根据main函数看出来。这里只是用了一部分的函数和宏,具体的可以参照linux/list.h中。差不多知道这些也够用了,等碰到问题了,再学习。
- 和菜鸟一起学linux之双向链表list head的简单实例
- 和菜鸟一起学linux之input系统简单实例
- 和菜鸟一起学linux之do{...}while(0)的简单实例
- 和菜鸟一起学linux之GCC内嵌汇编简单实例
- 和菜鸟一起学linux之GCC内嵌汇编简单实例
- 和菜鸟一起学linux之container_of实例
- 和菜鸟一起学linux之我的vim简单配置
- 和菜鸟一起学linux之我的vim简单配置
- 和菜鸟一起学linux之dlna的学习记录
- 和菜鸟一起学算法之递归和分治简单实例
- 和菜鸟一起学c之回调函数简单实例
- 和菜鸟一起学数据结构之简单静态链表实现
- 和菜鸟一起学OK6410之最简单字符驱动
- 和菜鸟一起学数据结构之简单单链表实现
- 和菜鸟一起学linux总线驱动之初识USB
- 和菜鸟一起学linux之V4L2摄像头应用流程
- 和菜鸟一起学linux之wifi学习记录基础知识
- 和菜鸟一起学linux之wifi学习记录
- zoj 3656 bit magic
- DEVICE_ATTR() 与 sysfs接口
- GPT分区在Dell服务器R715上安装linux不能引导的解决方法
- 需求分析
- google research
- 和菜鸟一起学linux之双向链表list head的简单实例
- Android:计算剩余内存
- android 权限管理和签名 实现静默卸载
- java 解析properties文件的两种方法
- 习惯与目标,关于自我超越
- Extjs4---常见错误集合
- Spring中使用JDBC
- 最近在做ts流转换成es流为移植到ti的8168板子上普及的基础知识
- 上海撞死5名养护工事故肇事者称当时在捡眼镜-瞌睡司机-酒驾司机-养护工人