Linux内核中双向链表的经典实现
2014-03-25 09:27
2271 查看
概要
前面一章"介绍双向链表并给出了C/C++/Java三种实现",本章继续对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法。其中,也会涉及到Linux内核中非常常用的两个经典宏定义offsetof和container_of。内容包括:1. Linux中的两个经典宏定义
2. Linux中双向链表的经典实现
转载请注明出处:https://www.geek-share.com/detail/2606710821.html
更多内容: 数据结构与算法系列 目录
Linux中的两个经典宏定义
倘若你查看过Linux Kernel的源码,那么你对 offsetof 和 container_of 这两个宏应该不陌生。这两个宏最初是极客写出的,后来在Linux内核中被推广使用。1. offsetof
1.1 offsetof介绍
定义:offsetof在linux内核的include/linux/stddef.h中定义。
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
说明:获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移量。
(01) ( (TYPE *)0 ) 将零转型为TYPE类型指针,即TYPE类型的指针的地址是0。
(02) ((TYPE *)0)->MEMBER 访问结构中的数据成员。
(03) &( ( (TYPE *)0 )->MEMBER ) 取出数据成员的地址。由于TYPE的地址是0,这里获取到的地址就是相对MEMBER在TYPE中的偏移。
(04) (size_t)(&(((TYPE*)0)->MEMBER)) 结果转换类型。对于32位系统而言,size_t是unsigned int类型;对于64位系统而言,size_t是unsigned long类型。
1.2 offsetof示例
代码(offset_test.c)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "list.h" struct person { int age; char name[20]; struct list_head list; }; void main(int argc, char* argv[]) { struct person *pperson; struct person person_head; struct list_head *pos, *next; int i; // 初始化双链表的表头 INIT_LIST_HEAD(&person_head.list); // 添加节点 for (i=0; i<5; i++) { pperson = (struct person*)malloc(sizeof(struct person)); pperson->age = (i+1)*10; sprintf(pperson->name, "%d", i+1); // 将节点链接到链表的末尾 // 如果想把节点链接到链表的表头后面,则使用 list_add list_add_tail(&(pperson->list), &(person_head.list)); } // 遍历链表 printf("==== 1st iterator d-link ====\n"); list_for_each(pos, &person_head.list) { pperson = list_entry(pos, struct person, list); printf("name:%-2s, age:%d\n", pperson->name, pperson->age); } // 删除节点age为20的节点 printf("==== delete node(age:20) ====\n"); list_for_each_safe(pos, next, &person_head.list) { pperson = list_entry(pos, struct person, list); if(pperson->age == 20) { list_del_init(pos); free(pperson); } } // 再次遍历链表 printf("==== 2nd iterator d-link ====\n"); list_for_each(pos, &person_head.list) { pperson = list_entry(pos, struct person, list); printf("name:%-2s, age:%d\n", pperson->name, pperson->age); } // 释放资源 list_for_each_safe(pos, next, &person_head.list) { pperson = list_entry(pos, struct person, list); list_del_init(pos); free(pperson); } }
View Code
运行结果:
==== 1st iterator d-link ==== name:1 , age:10 name:2 , age:20 name:3 , age:30 name:4 , age:40 name:5 , age:50 ==== delete node(age:20) ==== ==== 2nd iterator d-link ==== name:1 , age:10 name:3 , age:30 name:4 , age:40 name:5 , age:50
相关文章推荐
- Linux源文件的组织结构-转
- Linux操作系统基础理论(5)-----EXT2文件系统的实现机制
- Linux操作系统基础理论(4)-----Linux 存储管理的实现
- Linux操作系统基础理论(3)-----浅析Linux 与Minix 下进程实现的异同
- CentOS 6.5上部署DELL MD3200 存储备忘
- cd 命令
- ls命令
- cd命令
- 关于Linux下屏幕分辨率的调整
- tiny core linux ssh服务器(安装openssh)
- 一种在BIOS中嵌入应用程序的方法及实现 分类: arm-linux-Ubuntu 2014-03-25 08:33 524人阅读 评论(0) 收藏
- LinuxCast学习笔记三十四:SMB
- linux的防火墙端口配置
- linux 中关闭图形界面
- man stdio
- 2013年Linux“最佳项目”:Ubuntu、Android榜上有名
- 2013年Linux周刊读者投票出炉 Ubuntu、Android榜上有名
- linux 打包,压缩命令【实践】
- linux中fork()函数详解
- linux中fork()函数详解