Linux利用list_head结构实现双向链表
原文地址:http://www.cnblogs.com/bastard/archive/2012/10/19/2731107.html
通常实现双向链表的数据结构:

struct list_node1{
struct list_node1 *next,*prev;
type1 m1;
type2 m2;
};
struct list_node2{
struct list_node2 *next,*prev;
type1 m1;
type2 m2;
};
……

对于每一种数据结构都定义了其特定的实现链表的结构和对应的方法(add/del)操作链表;
但对于具有大量不同数据结构,都要使用链表的系统中,如果为每一种数据结构定义特定的结构,和操作方法,
无疑使代码变得重复和臃肿,需要实现一种通用的双向链表方法,对各种数据结构都能适用。
C语言中又没有C++里面的模板,该如何实现呢?
linux内核中大量使用如下数据结构实现双向链表:
struct list_head {
struct list_head *next, *prev;
};
如果需要有某种数据结构的双向队列,就在这种结构内部放一个list_head数据结构成员。
struct kobject {
const char *name;
struct list_head entry;
struct kobject *parent;
struct kset *kset;
}
形成了如下结构:
如何通过kobject 链表结构中的 list_head 成员entry访问下一个成员呢?
系统提供了宏list_entry:
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
//访问链表成员
kobject *obj = objList;
kobject *nextObj = (kobject *)list_entry(obj->entry->next,struct kobject,entry);
这个list_entry是什么道理呢:
ptr:是指向当前kobject结构对象中的数据成员entry,(char *)(ptr):entry成员地址 ——AddrA;
(unsigned long)(&((type *)0)->member)):将地址0转化为类型为type(struct kobject )对象,取member(entry)成员的地址——AddrB。
(type *)(AddrA - AddrB):得到kobject结构对象的首地址,转化为kobject对象。
这里需要关注的就是AddrB:将地址0转化为类型为type(struct kobject )对象,取member(entry)成员的地址。
表示当struct kobject 对象首地址为0时,得到成员member(entry)的地址,相对首地址的偏移地址。
通过struct kobject 对象中member(entry)的地址 ,以及相对首地址的偏移量,就能计算出struct kobject 对象的首地址。
如下结构:
充分利用了C语言中直接操作内存地址的特性。
Linux利用list_head结构实现双向链表的更多相关文章
- Linux 内核list_head 学习
Linux 内核list_head 学习(一) http://www.cnblogs.com/zhuyp1015/archive/2012/06/02/2532240.html 在Linux内核中,提 ...
- [转载]Linux 内核list_head 学习(一)
在Linux内核中,提供了一个用来创建双向循环链表的结构 list_head.虽然linux内核是用C语言写的,但是list_head的引入,使得内核数据结构也可以拥有面向对象的特性,通过使用操作li ...
- Linux内核kobject结构体分析
1.前言 Linux内核中有大量的驱动,而这些驱动往往具有类似的结构,根据面向对象的思想,可以将共同的部分提取为父类,而这个父类就是kobject,kobject结构体中包含了大量设备的必须信息,而三 ...
- Linux常用目录结构
此文引用自51CTO博客,博主snail_hf,原文地址<Linux系统目录详解(全而易懂)> 目录结构 / 根目录,处于Linux系统树形结构的最顶端,它是Linux文件系统的入口,所有 ...
- [转载]Linux内核list_head学习(二)
前一篇文章讨论了list_head 结构的基本结构和实现原理,本文主要介绍一下实例代码. 自己如果想在应用程序中使用list_head 的相应操作(当然应该没人使用了,C++ STL提供了list 用 ...
- (第五篇)Linux操作系统基本结构介绍
Linux操作系统基本结构介绍 Linux系统一般有4个主要部分:内核.shell.文件系统和应用程序.内核.shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序.管理文件并使用 ...
- (一)Linux之目录结构
Linux之目录结构 目录 Linux之目录结构 一.概述 一.基本介绍 二.具体的目录结构(不用背,知道即可) Linux /usr目录 Linux /var 目录 一.概述 学习 Linux,不仅 ...
- Linux内核--链表结构(一)
一.前言 Linux内核链表结构是一种双向循环链表结构,与传统的链表结构不同,Linux内核链表结构仅包含前驱和后继指针,不包含数据域.使用链表结构,仅需在结构体成员中包含list_head*成员就行 ...
- Linux 利用进程打开的文件描述符(/proc)恢复被误删文件
Linux 利用进程打开的文件描述符(/proc)恢复被误删文件 在 windows 上删除文件时,如果文件还在使用中,会提示一个错误:但是在 linux 上删除文件时,无论文件是否在使用中,甚至是还 ...
随机推荐
- zabbix 2.2 调小监控值
zabbix_agent默认disk下小于0%告警 调小到5% 组态 > 模板 选择需要的模板的触发器 例如 Template OS Windows 选择触发器 - 探索规则 - 触发器类型 ...
- CSS3 : box-shadow
box-shadow 用于设置边框阴影,语法: box-shadow: h-shadow v-shadow blur spread color inset; -moz-box-shadow: h-sh ...
- Laxcus大数据管理系统2.0(3)- 第一章 基础概述 1.2 产品特点
1.2 产品特点 Laxcus大数据管理系统运行在计算机集群上,特别强调软件对分布资源可随机增减的适应性.这种运行过程中数据动态波动和需要瞬时感知的特点,完全不同与传统的集中处理模式.这个特性衍生出一 ...
- java 生成简单word(利用Itext工具),生成简单Excel,以及下载笔记
1.java 生成简单word(包含图片表格) pom中加入itext 相关依赖 <dependency> <groupId>com.lowagie</groupId&g ...
- MySQL训练营03
[任务四] #任务时间# 请于4月6日22:00前完成,在[打卡表格]处打卡.逾期尚未打卡的会被清退. 4.1 MySQL 实战 #学习内容# 数据导入导出 将之前创建的任意一张MySQL表导出,且是 ...
- UVA 11882 Biggest Number(搜索+剪枝)
You have a maze with obstacles and non-zero digits in it: You can start from any square, walk in the ...
- jQuery添加、移除、改变class属性
jQuery中一般有3个关于改变元素class的函数addClass.removeClass.toggleClass addClass描述: 为每个匹配的元素添加指定的样式类名$('div').add ...
- Delphi 7学习开发控件(续)
继上次我们学习开发一个简单的画线控件后,基本的制作控件步骤已经清楚了,这次我们继续加深学习控件的制作.我们打开Delphi 7创建一个应用程序,拖动LineTo控件到窗体上,仔细看左边的对象设计器,可 ...
- Oracle解决索引碎片功能
我们开始时向一个空的带索引的表中插入大量数据后,是不会产生碎片问题的,但是,数据库经过很长一段时间的增删改查后,难免会出现碎片问题,影响数据库的性能,Oracle对于这一问题有自己的解决方案. 下面介 ...
- 【bzoj1001】[BeiJing2006]狼抓兔子 最小割+对偶图+最短路
题目描述 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: ...