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 上删除文件时,无论文件是否在使用中,甚至是还 ...
随机推荐
- 51单片机数码管字符H自右向左移动
#include <reg51.h> #define uint unsigned int #define uchar unsigned char sfr P0M0 = 0x94; sfr ...
- Python3 初识Python
一 Python简介 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC ...
- Uva 12627 Erratic Expansion(递归)
这道题大体意思是利用一种递归规则生成不同的气球,问在某两行之间有多少个红气球. 我拿到这个题,一开始想的是递归求解,但在如何递归求解的思路上我的方法是错误的.在研读了例题上给出的提示后豁然开朗(顺便吐 ...
- Mac下安装OpenCV问题
最近看了纹理特征方面的paper,看了一些资料之后,想要实际动手实现一下其中LBP算法,果然OpenCV中已经实现. 问题 No module named "cv2" 当我在我们项 ...
- PokeCats开发者日志(八)
现在是PokeCats游戏开发的第十四天的中午,很不幸著作权申请又被打回来了. 据说是排版后代码行数还差500行,文档不足十版.我擦,原来他们会自己排版的啊. 只好从项目自带的xml里扣代 ...
- Aspose.Pdf合并图片到PDF文件
将图片和PDF文件合成为新的PDF文件,可以先将图片转换为PDF文件, 然后合成PDF即可, 将图片转换成PDF文件有如下方法: Aspose.Pdf.Document Aspose.Pdf.Gene ...
- SpringBoot2.0
建立可执行的Jars和Wars bootJar用于构建可执行的Jar: bootWar用于构建可执行的war. application.properties 不启动web服务器 spring.main ...
- ASP.NET页面之间传值QueryString(1)
QueryString是一种非常简单的传值方式,他可以将传送的值显示在浏览器的地址栏中.如果是传递一个或多个安全性要求不高或是结构简单的数值时,可以使用这个方法.但是对于传递数组或对象的话,就不能用这 ...
- P1118 [USACO06FEB]数字三角形`Backward Digit Su`…
题目描述 FJ and his cows enjoy playing a mental game. They write down the numbers from 11 to N(1 \le N \ ...
- Winpcap网络开发库入门
原文链接地址:http://www.cnblogs.com/phinecos/archive/2008/10/20/1315176.html Winpcap是一个强大的网络开发库,可以实现许多功能:获 ...