Linux 巨集定義container of詳解

2021-09-07 18:23:32 字數 1906 閱讀 6550

在寫linux驅動的過程中經常是乙個結構體套一層結構體,而在某些函式中傳入的引數是子結構體指標,但是我們又需要獲取的其外層結構體的資料,linux為我們提供了container_of巨集定義來為我們解決這個問題。

container_of巨集定義就是用來通過內層結構體的指標獲取外層結構體指標,巨集定義很巧妙,我等凡人想不出來。下面就詳細分析其實現原理吧。

container_of巨集定義需要用到offsetof巨集,現在offsetof巨集的功能已經變成乙個gcc的內建函式了__builtin_offsetof (type, member),但offsetof巨集實際定義可由第二行定義實現。

#define offsetof(type, member) __builtin_offsetof (type, member)

#define offsetof(type, member) ((size_t)&((type *)0)->member)

#define container_of(ptr, type, member) ()

offsetof(type, member)的操作過程:

首先分析offsetof巨集,其功能是獲得成員membertype結構中的偏移量。

container_of(ptr, type, member)的操作過程:

仔細分析會發現,其實根本沒有必要定義第一句,只需一句就可以實現:

#define container_of(ptr, type, member) (

)

但是為什麼會定義第一句呢?其實主要為了對ptrmember做型別檢查,如果用typeof求出來的型別和ptr不一致,那麼在賦值操作時,編譯器會報錯。

可能會有仁兄有疑問:0位址訪問資料,不會出現非法位址訪問的錯誤嗎?

仔細分析,這裡並沒有發生0位址的附近資料的訪問,仔細看看僅僅發生了&取位址、typeof取型別操作,因此不會存在非法訪問記憶體的問題。

新的核心對此又有了新的定義:

/* are two types/vars the same type (ignoring qualifiers)? */

#ifndef __same_type

# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))

#endi

#define container_of(ptr, type, member) ({ \

void *__mptr = (void *)(ptr); \

build_bug_on_msg(!__same_type(*(ptr), ((type *)0)->member) && \

!__same_type(*(ptr), void), \

"pointer type mismatch in container_of()"); \

((type *)(__mptr - offsetof(type, member)));

有2個新變化:

第一,用void *取代了char *來做減法,

第二,用__same_type巨集來做型別檢測,錯了有明確的資訊提示。

好了,以後繼續把鍊錶相關的操作也搬上來。

linux 核心 THIS MODULE巨集定義詳解

結構體struct module在核心中代表乙個核心模組,通過insmod 實際執行init module系統呼叫 把自己編寫的核心模組插入核心時,模組便與乙個 struct module結構體相關聯,並成為核心的一部分。下面是結構體struct module的完整定義,接下來會逐個解釋 struc...

abs int 巨集定義 巨集定義和巨集方法

巨集定義和巨集方法 定義機型 define is iphone5 uiscreen instancesrespondtoselector selector currentmode cgsizeequaltosize cgsizemake 640,1136 uiscreen mainscreen cu...

C 巨集定義 巨集定義求面積

學過c語言的讀者,對巨集定義應該不陌生,同樣在c 中,也可以用巨集定義命令將乙個指定的識別符號來代表乙個字串,巨集定義的作用一般是用乙個短的名字代表乙個長的字串。一般形式為 define 識別符號 字串定義pi的符號常量 define pi 3.14在c 中還可以用 define命令定義帶引數的巨集...