加入收藏 | 设为首页 | 会员中心 | 我要投稿 佛山站长网 (https://www.0757zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux内核中双向链表的经典实现

发布时间:2016-10-13 19:44:58 所属栏目:Linux 来源:网络整理
导读:概要 前面一章介绍双向链表并给出了C/C++/Java三种实现,本章继续对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法。其中,也会涉及到Lin

结果:

gender_offset = 0
id_offset = 4
age_offset = 8
name_offset = 12

说明:简单说说"为什么id的偏移值是4,而不是1"。我的运行环境是linux系统,32位的x86架构。这就意味着cpu的数据总线宽度为32,每次能够读取4字节数据。gcc对代码进行处理的时候,是按照4字节对齐的。所以,即使gender是char(一个字节)类型,但是它仍然是4字节对齐的!

1.3 offsetof图解

Linux内核中双向链表的经典实现

TYPE是结构体,它代表"整体";而MEMBER是成员,它是整体中的某一部分。

将offsetof看作一个数学问题来看待,问题就相当简单了:已知'整体'和该整体中'某一个部分',而计算该部分在整体中的偏移。

2. container_of

2.1 container_of介绍

定义:container_of在linux内核的include/linux/kernel.h中定义。

#define container_of(ptr, type, member) ({          
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    
    (type *)( (char *)__mptr - offsetof(type,member) );})

说明:根据"结构体(type)变量"中的"域成员变量(member)的指针(ptr)"来获取指向整个结构体变量的指针。

(01) typeof( ( (type *)0)->member )     取出member成员的变量类型。

(02) const typeof( ((type *)0)->member ) *__mptr = (ptr)    定义变量__mptr指针,并将ptr赋值给__mptr。经过这一步,__mptr为member数据类型的常量指针,其指向ptr所指向的地址。

(04) (char *)__mptr    将__mptr转换为字节型指针。

(05) offsetof(type,member))    就是获取"member成员"在"结构体type"中的位置偏移。

(06) (char *)__mptr - offsetof(type,member))    就是用来获取"结构体type"的指针的起始地址(为char *型指针)。

(07) (type *)( (char *)__mptr - offsetof(type,member) )    就是将"char *类型的结构体type的指针"转换为"type *类型的结构体type的指针"。

2.2 container_of示例

代码(container_test.c)

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 // 获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移量。
 5 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
 6 
 7 // 根据"结构体(type)变量"中的"域成员变量(member)的指针(ptr)"来获取指向整个结构体变量的指针
 8 #define container_of(ptr, type, member) ({          
 9     const typeof( ((type *)0)->member ) *__mptr = (ptr);    
10     (type *)( (char *)__mptr - offsetof(type,member) );})
11 
12 struct student
13 {
14     char gender;
15     int id;
16     int age;
17     char name[20];
18 };
19 
20 void main()
21 {
22     struct student stu;
23     struct student *pstu;
24 
25     stu.gender = '1';
26     stu.id = 9527;
27     stu.age = 24;
28     strcpy(stu.name, "zhouxingxing");
29 
30     // 根据"id地址" 获取 "结构体的地址"。
31     pstu = container_of(&stu.id, struct student, id);
32 
33     // 根据获取到的结构体student的地址,访问其它成员
34     printf("gender= %cn", pstu->gender);
35     printf("age= %dn", pstu->age);
36     printf("name= %sn", pstu->name);
37 }

本栏目更多精彩内容:http://www.bianceng.cn/OS/Linux/

(编辑:佛山站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读