linux核心中的container_of宏

來源:互聯網
上載者:User

        //xk> 引子

        首先看一個簡單的面試題:定義一個宏FIND(stru, e),求結構體stru中某個成員e相對於stru的位移量。

        題目的解答很簡單:

#define FIND(stru, e) &(((stru *)0)->e)

將常量0強制類型轉化為stru *類型的指標。因為結構體的首地址為0,所以其成員的地址即為相對於結構體的位移量。

        順便提一點,C++中不能直接用&對一個類的成員函數取地址,實現這個目的的技巧參見《C++編程思想》。C++中可以直接用&對一個類的資料成員取地址,因為資料成員和成員函數存放在不同的記憶體區。

        //xk> 本文

        Linux中廣泛運用容器機制。如果struct A中嵌入包含一個子結構B,則稱A是B的一個容器。

        比如作為Linux標準資料結構的迴圈雙鏈表,是由一個一個的表頭串連起來的,而這些表頭就嵌入在雙鏈表所管理的各種類型的對象之中。注意這裡的表頭不是指鏈表的表頭,而是鏈表的元素,是被管理對象在鏈表中的引子,很多時候我們稱被管理對象為鏈表元素。這樣做有兩個好處:1. 被管理的對象可能類型迥異,而表頭的結構統一而簡單。2. 雙鏈表應用非常廣泛,因為表頭結構統一,核心可以提供一套標準的迴圈雙鏈表操作。

        通過迴圈雙鏈表很容易找到鏈表上的某個表頭,我們關注的是怎樣通過嵌入在容器中的表頭,找到被管理的那個對象的首地址。

        以迴圈雙鏈表為例,list_entry宏提供了這個功能

// list.h#define list_entry(ptr, type, member) container_of(ptr, type, member)

而container_of宏則是核心真正用來實現該目的的宏:根據嵌入的子結構成員返回容器首地址。

        根據成員返回結構首地址,簡言之:成員的地址 - 成員相對於結構首地址的便宜量 = 結構首地址。linux核心提供offsetof宏來做這個事情

// kernel.h#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)    // 訪問結構指標成員操作符-> 的優先順序高於 取地址操作符&

        注意操作符優先順序:訪問結構指標成員操作符-> 高於 取地址操作符& 高於 強制類型轉換操作符()

        到這裡都很簡單,不過下一步形式有點複雜:

// kernel.h/** * container_of 從結構的成員來獲得容器執行個體 * @ptr:            指向成員資料的指標 * @type:          容器結構的類型 * @member:    成員在容器內的名稱 */#define container_of(ptr, type, member) \({ \    const typeof( ((type *)0)->member) *__mptr = (ptr); \    (type *)( (char *)__mptr - offsetof(type, member) ); \})

        其核心依然很簡單,兩步走:

        (1) 建立一個指標__mptr,其值等於ptr。其類型為member的類型。(《深入linux核心架構》說其類型為type,還舉了個例子,應該是錯的,指標不能隱式類型轉換,所以__mptr與ptr類型相同才能賦值)

        (2) __mptr - 位移量即得到首地址。強制類型轉換(char *)是為了保證指標運算以位元組為單位。通常指標運算表示指向數組的下一個元素,因此指標 + 1的結果與指標的類型相關。強制類型轉換(type *)是因為這個宏的結果應該是容器結構的類型type,返回的是容器結構首地址嘛。

        為啥不直接用ptr,而要產生一個const的__mptr呢?難道container_of宏可能修改ptr?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.