Linux list_head
在linux kernel里面链表应用非常广泛。
我们在应用程序中,定义一个链表结构通常要包含数据域,如下:
typedef struct _listNode{
int data;
struct _listNode *prev, *next;
}ListNode;
但在内核代码中,定义的链表都没有数据域, 如下:
struct list_head {
struct list_head *next, *prev;
};
如果需要定义双链表结构,则在数据结构中包含一个list_head的成员变量,
struct book{
int data;
struct list_head list;
}
假设我们有另外一个结构体person,里面也有一个链表,这个链表是book的双链表。(代表一个人有多本书)
struct person{
char *name;
int booknum;
struct list_head booklist;
}
我们在初始化时,创建book的结构,并且将book加入到person的book list中。
struct person *myperson;
book= kmalloc(sizeof(struct book), GFP_KERNEL);
list_add_tail(&book->list, &myperson->booklist);
person->booknum++
那么后续我们知道booklist结构的地址(address A),如何知道booklist中的book结构(address B)呢?

struct book mybook;
list_for_each_entry(mybook, &myperson->booklist, list) //遍历myperson->booklist,每个元素放在mybook.
#define list_for_each_entry(pos, head, member) \
for (pos = list_first_entry(head, typeof(*pos), member); \
&pos->member != (head); \
pos = list_next_entry(pos, member))
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
最终展开的myperson->booklist的第一个元素的book结构为list_entry((&myperson->booklist)->next, struct book, list)
可以看出通过list_entry来获取myperson->booklist中的book结构。
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#define container_of(ptr, type, member) ({ \//ptr为(&myperson->booklist)的元素的地址(address A),type为实际的结构struct book,list是book中的list成员名字
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
将list_entry展开
((struct book*)((char *)((&myperson->booklist)->next)-(size_t)(&((struct book *)0)->list)))
(unsigned long)(&((struct book *)0)->list))即list相对于book 首地址的偏移(上图的offset)。
1. ( (type*)0 ) 将零转型为type类型指针;
2. ((tpye*)0)->member访问结构中的数据成员;
3. &( ( (type*)0 )->member)取出数据成员的地址;
4.(size_t)(&(((type*)0)->member))转换成size_t类型,即member相对type结构首地址的偏移。
myperson的booklist 的地址(address A) 减去 偏移(offset)即为book结构首地址(Address B)。
Linux list_head的更多相关文章
- Linux 驱动开发
linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...
- linux 内核分析之list_head
转自:http://www.cnblogs.com/riky/archive/2006/12/28/606242.html 一.链表数据结构简介 链表是一种常用的组织有序数据的数据结构,它通过指针将一 ...
- linux内核的双链表list_head、散列表hlist_head
一.双链表list_head 1.基本概念 linux内核提供的标准链表可用于将任何类型的数据结构彼此链接起来. 不是数据内嵌到链表中,而是把链表内嵌到数据对象中. 即:加入链表的数据结构必须包含一个 ...
- Linux 内核list_head 学习
Linux 内核list_head 学习(一) http://www.cnblogs.com/zhuyp1015/archive/2012/06/02/2532240.html 在Linux内核中,提 ...
- Linux利用list_head结构实现双向链表
原文地址:http://www.cnblogs.com/bastard/archive/2012/10/19/2731107.html 通常实现双向链表的数据结构: struct list_node1 ...
- [转载]Linux内核list_head学习(二)
前一篇文章讨论了list_head 结构的基本结构和实现原理,本文主要介绍一下实例代码. 自己如果想在应用程序中使用list_head 的相应操作(当然应该没人使用了,C++ STL提供了list 用 ...
- [转载]Linux 内核list_head 学习(一)
在Linux内核中,提供了一个用来创建双向循环链表的结构 list_head.虽然linux内核是用C语言写的,但是list_head的引入,使得内核数据结构也可以拥有面向对象的特性,通过使用操作li ...
- Linux内核中的双向链表struct list_head
一.双向链表list_head Linux内核驱动开发会经常用到Linux内核中经典的双向链表list_head,以及它的拓展接口和宏定义:list_add.list_add_tail.list_de ...
- go例子(一) 使用go语言实现linux内核中的list_head
package list 代码 package list import ( "fmt" ) // 数据接口 type ElemType interface{} // 节点 type ...
随机推荐
- (转)java中新生代和老年代
转自:http://blog.csdn.net/lojze_ly/article/details/49456255 聊聊JVM的年轻代 1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不 ...
- 浅谈radis
1.概述 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API 从2010年3月15日起,Redis的开发工作由VM ...
- 关于 RMAN 控制文件自动备份路径中指定的 %F 说明
默认情况下,RMAN备份的属性配置一共 14 行( show all; )来自博客园AskScuti CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVIC ...
- python 多版本环境
参考 https://www.cnblogs.com/---JoyceLiuHome/articles/7852871.html 安装 Anaconda集成化环境 https://www.anacon ...
- 跨站点脚本攻击XSS
来源:http://www.freebuf.com/articles/web/15188.html 跨站点脚本攻击是一种Web应用程序的攻击,攻击者尝试注入恶意脚本代码到受信任的网站上执行恶意操作.在 ...
- pytest学习1-安装和入门
一.安装pytest: 在命令行窗口下执行: pip install -U pytest 检查安装的pytest版本: pytest -v 二.运行第一个测试用例: import pytest def ...
- xshell如何将Windows文件上传到linux
1. 首先先将你xshell配置好用户名及密码等,必须使用有权限下载的账号进行操作. 使用 yum provides */rz 这条命令,查看你系统自带的软件包的信息. 2.在输出的信息中可 ...
- 搭建Hexo实现个人网站详细教程
全网最全小白搭建Hexo+Gitee/Coding/Github 全网最全小白搭建Hexo+Gitee/Coding/Github 本站内容已全部转移到https://www.myyuns.ltd,具 ...
- ssh: connect to git@gitlab.xxxxx.com:xxxxx.git port 22: Connection refused
公司服务器上的gitlab项目添加了ssh密钥,但是操作时却报错ssh: connect to git@gitlab.xxxxx.com:xxxxx.git port 22: Connection r ...
- web前端基础-css-尺寸边框
尺寸和边框: 一.尺寸 行内元素是不能设置宽和高的,其高度是由元素里面的内容的高度撑起来的: 行内块元素可以设置宽和高,当行内块元素没有设置宽高的时候,行内块元素的宽高是其默认的宽高: 块级元素:可以 ...