原文地址: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结构实现双向链表的更多相关文章

  1. Linux 内核list_head 学习

    Linux 内核list_head 学习(一) http://www.cnblogs.com/zhuyp1015/archive/2012/06/02/2532240.html 在Linux内核中,提 ...

  2. [转载]Linux 内核list_head 学习(一)

    在Linux内核中,提供了一个用来创建双向循环链表的结构 list_head.虽然linux内核是用C语言写的,但是list_head的引入,使得内核数据结构也可以拥有面向对象的特性,通过使用操作li ...

  3. Linux内核kobject结构体分析

    1.前言 Linux内核中有大量的驱动,而这些驱动往往具有类似的结构,根据面向对象的思想,可以将共同的部分提取为父类,而这个父类就是kobject,kobject结构体中包含了大量设备的必须信息,而三 ...

  4. Linux常用目录结构

    此文引用自51CTO博客,博主snail_hf,原文地址<Linux系统目录详解(全而易懂)> 目录结构 / 根目录,处于Linux系统树形结构的最顶端,它是Linux文件系统的入口,所有 ...

  5. [转载]Linux内核list_head学习(二)

    前一篇文章讨论了list_head 结构的基本结构和实现原理,本文主要介绍一下实例代码. 自己如果想在应用程序中使用list_head 的相应操作(当然应该没人使用了,C++ STL提供了list 用 ...

  6. (第五篇)Linux操作系统基本结构介绍

    Linux操作系统基本结构介绍 Linux系统一般有4个主要部分:内核.shell.文件系统和应用程序.内核.shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序.管理文件并使用 ...

  7. (一)Linux之目录结构

    Linux之目录结构 目录 Linux之目录结构 一.概述 一.基本介绍 二.具体的目录结构(不用背,知道即可) Linux /usr目录 Linux /var 目录 一.概述 学习 Linux,不仅 ...

  8. Linux内核--链表结构(一)

    一.前言 Linux内核链表结构是一种双向循环链表结构,与传统的链表结构不同,Linux内核链表结构仅包含前驱和后继指针,不包含数据域.使用链表结构,仅需在结构体成员中包含list_head*成员就行 ...

  9. Linux 利用进程打开的文件描述符(/proc)恢复被误删文件

    Linux 利用进程打开的文件描述符(/proc)恢复被误删文件 在 windows 上删除文件时,如果文件还在使用中,会提示一个错误:但是在 linux 上删除文件时,无论文件是否在使用中,甚至是还 ...

随机推荐

  1. 自动化测试学习之路--java 数组

    数组的定义与为数组元素分配空间和赋值是分开进行的,称为动态初始化. 在数组定义的同时就为数组元素分配空间并赋值,称为静态初始化. 一维数组举例: //动态初始化 int[] intArr; intAr ...

  2. selenide 自动化UI测试中Configuration全局配置项目

    selenide 在测试过程中需要设置许多的默认值,方便在测试过程中进行和很好的使用.下面我们在selenide中的api引用过来看看! static Configuration.AssertionM ...

  3. LAMP架构应用实战—Apache服务介绍与安装01

    LAMP架构应用实战—Apache服务介绍与安装01   一:Apache是什么 Apache是Apache基金会开发的一个高性能.功能强大.安全可靠.灵活的开放源码的WEB服务软件 二:Apache ...

  4. DFS实现模板

    以如下图的无向图G4为例,进行图的深度优先搜索: 假设从顶点v1出发进行搜索,在访问了顶点v1之后,选择邻接点v2.因为v2未曾访问,则从v2出发进行搜索.依次类推,接着从v4 .v8 .v5出发进行 ...

  5. HDU B-Ignatius and the Princess IV

    http://acm.hdu.edu.cn/showproblem.php?pid=1029 Problem Description "OK, you are not too bad, em ...

  6. SQL 视图 局部变量 全局变量 条件语句 事务 触发器

    一.视图 1.视图是一张虚拟表,他所存储的不是实际数据,而是查询语句,但我们可以对视图进行像数据表一样的操作. 2.为什么使用视图呢?我的理解是:1.在远程传输数据时,可以避免过长的查询字符,减少流量 ...

  7. SSH整合主要XML代码

    web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version="2 ...

  8. Dubbo 的 Helloworld

    前提条件 安装好了 ZooKeeper 作为注册中心 服务端 <?xml version="1.0" encoding="UTF-8"?> < ...

  9. post 中文乱码处理 接受的编码--->解码成字节数组(无任何编码形式)----->编码成想要的格式

  10. HDU 4776 Ants(Trie+优先队列)

    Ants Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others) Total S ...