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 上删除文件时,无论文件是否在使用中,甚至是还 ...
随机推荐
- 自动化测试学习之路--java String、StringBuilder
Java中的String和StringBuilder类: 1.String对象是不可变的.每一个看起来修改了String值的方法,实际上都是创建了全新的String对象.代码示例如下: String ...
- Halcon环境搭建
1.Visual Studio 2017安装教程 2.Qt5.9安装教程 3.VS2017中Qt插件安装教程
- JavaScript 面向对象 原型(prototype) 继承
1.对象的概念:无需属性的集合,属性可以为数值,对象或函数,ECMAscript中没有类的概念,这点是javascript与其他面向对象(OO)语言不同的地方. //创建一个自定义对象 var per ...
- 并查集——poj2236(带权并查集)
题目:Wireless Network 题意:给定n台已损坏计算机的位置和计算机最远通信距离d,然后分别根据命令执行以下两种操作: "O p" (1 <= p <= N ...
- DFS(4)——hdu1010Tempter of the Bone
一.题目回顾 题目链接:Tempter of the Bone Problem Description The doggie found a bone in an ancient maze, whic ...
- 甲级1002 A+B for Polynomials (25)
题目描述: This time, you are supposed to find A+B where A and B are two polynomials. Input Each input fi ...
- 【EasyNetQ】- 使用Future Publish调度事件
许多业务流程要求在将来某个日期安排事件.例如,在与客户进行初次销售联系后,我们可能希望在将来的某个时间安排跟进电话.EasyNetQ可以通过其Future Publish功能帮助您实现此功能.例如,这 ...
- Java IO 小结
Java IO 的学习需要明白流设计的体系结构,这样才能在实际需要的时候,通过API文档查阅,快速实现功能.
- 【bzoj1797】[Ahoi2009]Mincut 最小割 网络流最小割+Tarjan
题目描述 给定一张图,对于每一条边询问:(1)是否存在割断该边的s-t最小割 (2)是否所有s-t最小割都割断该边 输入 第一行有4个正整数,依次为N,M,s和t.第2行到第(M+1)行每行3个正 整 ...
- 【题解】SDOI2011消耗战
虚树模板题~洛谷P2495 第一次写虚树,感觉好厉害呀~首先,这道题目的树形dp是非常显然的,要控制一个点&其子树所有点,要么在子树内部割边,要么直接切点该点与父亲的连边.所以dp[u]表示控 ...