Linux Kernel:  container_of 黑科技

 1 #include<stdio.h>
 2
 3 #define offsetof(TYPE,MEMBER)  ((size_t)&((TYPE*)0)->MEMBER)
 4
 5 #define container_of(ptr,type,member) ({       6     const typeof( ((type*)0)->member ) *__mptr = (ptr);   7     (type *)( (char *)__mptr - offsetof(type,member) );})
 8
 9
10 #define list_entry(ptr,type,member) 11     container_of(ptr,type,member)
12
13 struct MyStruct {
14     int i_1;
15     int i_2;
16     int i_3;
17     int i_4;
18     int i_5;
19     int i_6;
20     int i_7;
21     int i_8;
22     int i_9;
23     int i_a;
24     int i_b;
25     int i_c;
26     int i_d;
27     int i_e;
28     int i_f;
29     int i_g;
30     int i_h;
31     int i_j;
32 };
33
34 int main()
35 {
36     struct MyStruct Test = { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18};
37     printf("Just a test: Test->i_1: %d\n",Test.i_1);
38     int *ptr = &(Test.i_2);
39     printf("Now we got i_2: %d \n",*ptr);
40     struct MyStruct *struct_ptr = container_of(ptr,struct MyStruct,i_2);
41     printf("Now we got struct\n");
42     printf("Test.i_3 is: %d \n",struct_ptr->i_3);
43
44     return 0;
45 }

由一个struct里的member(成员)的指针得到这个struct的指针,从而可以得到这个struct的其他成员。

通过这种方法,Linux内部就不需要维护一个task_struct的双向链表了,只需要维护task_struct里面的某个成员的双向链表,效果等同于一个task_struct的双向链表。这样就可以节省空间。而通过上面的黑科技,有可以达到双向链表的效果,一举两得。

(task_struct是Linux Kernel内部用来描述一个process/thread的struct,维护一个task_struct的双向链表是因为要从一个进程得到其子进程、父进程、兄弟进程......)

可以看出其实这个黑科技之所以能实现主要是因为gcc那个 typeof 操作符......

:)

时间: 2024-10-20 05:20:15

Linux Kernel:  container_of 黑科技的相关文章

Linux Kernel 开发报告 25 周年版

Linux基金会发布 2016 年度 Linux 内核开发报告,这次恰逢 Linux 内核 25 周年(腾云科技ty300.com),所以相比往年又更多的回顾性内容,值得一读. Linux 内核开发报告 2016 版 一些有趣的信息: 自 3.18 内核以来,合并自Linux Kernel内核的新功能覆盖面更为广泛,且涉及安全性的新功能越来越多 4.0 系列的引入仅仅是由于 Linus (基础教程qkxue.net)觉得小版本号已经超越正常人手指和脚趾数量的总和了.每一个内核版本发布都是传统意义

深入浅出实例解析linux内核container_of宏

做一件事情首先应该知道它的目的是什么. container_of的目的:如何通过结构中的某个变量获取结构本身的指针. 总体思路:假想一下,你的结构体中有好几个成员,你如何通过里面的"任一成员"获取整个结构体的首地址呢.container_of的做法就是通过typeof定义一个与"任一成员"同类型的指针变量pvar_a(假设变量名就是pvar_a),并让指针变量pvar_a指向这个"任一成员",然后用 "pvar_a的地址" 减

linux kernel的中断子系统之(三):IRQ number和中断描述符【转】

转自:http://www.wowotech.net/linux_kenrel/interrupt_descriptor.html 一.前言 本文主要围绕IRQ number和中断描述符(interrupt descriptor)这两个概念描述通用中断处理过程.第二章主要描述基本概念,包括什么是IRQ number,什么是中断描述符等.第三章描述中断描述符数据结构的各个成员.第四章描述了初始化中断描述符相关的接口API.第五章描述中断描述符相关的接口API. 二.基本概念 1.通用中断的代码处理

Linux kernel中断子系统之(五):驱动申请中断API

一.前言 本文主要的议题是作为一个普通的驱动工程师,在撰写自己负责的驱动的时候,如何向Linux Kernel中的中断子系统注册中断处理函数?为了理解注册中断的接口,必须了解一些中断线程化(threaded interrupt handler)的基础知识,这些在第二章描述.第三章主要描述了驱动申请 interrupt line接口API request_threaded_irq的规格.第四章是进入request_threaded_irq的实现细节,分析整个代码的执行过程. 二.和中断相关的lin

linux kernel的中断子系统之(四):High level irq event handler

一.前言 当外设触发一次中断后,一个大概的处理过程是: 1.具体CPU architecture相关的模块会进行现场保护,然后调用machine driver对应的中断处理handler 2.machine driver对应的中断处理handler中会根据硬件的信息获取HW interrupt ID,并且通过irq domain模块翻译成IRQ number 3.调用该IRQ number对应的high level irq event handler,在这个high level的handler中

linux kernel的中断子系统之(九):tasklet

一.前言 对于中断处理而言,linux将其分成了两个部分,一个叫做中断handler(top half),属于不那么紧急需要处理的事情被推迟执行,我们称之deferable task,或者叫做bottom half,.具体如何推迟执行分成下面几种情况: 1.推迟到top half执行完毕 2.推迟到某个指定的时间片(例如40ms)之后执行 3.推迟到某个内核线程被调度的时候执行 对于第一种情况,内核中的机制包括softirq机制和tasklet机制.第二种情况是属于softirq机制的一种应用场

Linux Kernel: the &quot; do { ... } while(0)&quot; magic

在读Linux源码的时候看到一堆这种macro: #define FOO(X) do { f(X); g(X); } while (0) 一直想不明白,为什么不直接用 #define FOO(X) f(x);g(x); 或者: #define FOO(X) {f(x);g(x);} 搜了一下才明白: http://stackoverflow.com/questions/9495962/why-use-do-while-0-in-macro-definition http://stackoverf

最具颠覆力的十大黑科技,你最期待哪一个?

科技技术水平的提高,有些先进技术对于未来各行业的发展提供了积极的一面,但是也不免会出现一些具有颠覆力的黑科技.那么,对于最具颠覆力的黑科技,你了解多少呢?下面十大排行网(Top10.ph)就来盘点下最具颠覆力的十大黑科技. 10.SCiO:从分子层面认识物质 SCiO是以色列一家名为ConsumerPhysics的初创公司生产的便携近红外光谱分析仪,体积和大拇指差不多,只轻轻一扫,它就能够告诉你身边常见物品的化学成分,并将扫描和计算结果直接发送到你的手机.如:检测食物的营养信息;检测食用油的质量

linux kernel的中断子系统之(八):softirq

一.前言 对于中断处理而言,linux将其分成了两个部分,一个叫做中断handler(top half),是全程关闭中断的,另外一部分是deferable task(bottom half),属于不那么紧急需要处理的事情.在执行bottom half的时候,是开中断的.有多种bottom half的机制,例如:softirq.tasklet.workqueue或是直接创建一个kernel thread来执行bottom half(这在旧的kernel驱动中常见,现在,一个理智的driver厂商是