linux 核心原始碼中的idr機制

2021-07-26 07:02:49 字數 2585 閱讀 6495

原文:

idr在linux核心中指的就是整數id管理機制,從本質上來說,這就是一種將整數id號和特定指標關聯在一起的機制。這個機制最早是在2023年2月加入核心的,當時是作為posix定時器的乙個補丁。現在,在核心的很多地方都可以找到idr的身影。

idr機制適用在那些需要把某個整數和特定指標關聯在一起的地方。舉個例子,在i2c匯流排中,每個裝置都有自己的位址,要想在匯流排上找到特定的裝置,就必須要先傳送該裝置的位址。如果我們的pc是乙個i2c匯流排上的主節點,那麼要訪問匯流排上的其他裝置,首先要知道他們的id號,同時要在pc的驅動程式中建立乙個用於描述該裝置的結構體。

此時,問題來了,我們怎麼才能將這個裝置的id號和他的裝置結構體聯絡起來呢?最簡單的方法當然是通過陣列進行索引,但如果id號的範圍很大(比如32位的id號),則用陣列索引顯然不可能;第二種方法是用鍊錶,但如果網路中實際存在的裝置較多,則鍊錶的查詢效率會很低。遇到這種清況,我們就可以採用idr機制,該機制內部採用radix樹實現,可以很方便地將整數和指標關聯起來,並且具有很高的搜尋效率。

(1)獲得idr

要在**中使用idr,首先要包括。接下來,我們要在**中分配idr結構體,並初始化:

void idr_init(struct idr *idp);

其中idr定義如下:

struct idr ;

/* idr是idr機制的核心結構體 */

(2)為idr分配記憶體

int idr_pre_get(struct idr *idp, unsigned int gfp_mask);

每次通過idr獲得id號之前,需要先分配記憶體。

返回0表示錯誤,非零值代表正常

(3)分配id號並將id號和指標關聯

int idr_get_new(struct idr *idp, void *ptr, int *id);

int idr_get_new_above(struct idr *idp, void *ptr, int start_id, int *id);

idp: 之前通過idr_init初始化的idr指標

id:  由核心自動分配的id號

ptr: 和id號相關聯的指標

start_id: 起始id號。核心在分配id號時,會從start_id開始。如果為i2c節點分配id號,可以將裝置位址作為start_id

函式呼叫正常返回0,如果沒有id可以分配,則返回-enospc

在實際中,上述函式常常採用如下方式使用:

again:

if (idr_pre_get(&my_idr, gfp_kernel) == 0)

spin_lock(&my_lock);

result = idr_get_new(&my_idr, &target, &id);

if (result == -eagain)

(4)通過id號搜尋對應的指標

void *idr_find(struct idr *idp, int id);

返回值是和給定id相關聯的指標,如果沒有,則返回null

(5)刪除id

要刪除乙個id,使用:

void idr_remove(struct idr *idp, int id);

通過上面這些方法,核心**可以為子裝置,inode生成對應的id號。這些函式都定義在中

下面,我們通過分析i2c協議的核心**,來看一看idr機制的實際應用:

.../* idr標頭檔案 */

...static define_idr(i2c_adapter_idr); /* 宣告idr */

.../* 

採用動態匯流排號宣告並註冊乙個i2c介面卡(adapter),可睡眠

針對匯流排號可動態指定的裝置,如基於usb的i2c裝置或pci卡

*/int i2c_add_adapter(struct i2c_adapter *adapter)

adapter->nr = id;

return i2c_register_adapter(adapter);

}export_symbol(i2c_add_adapter);

/* 採用靜態匯流排號宣告並註冊乙個i2c介面卡(adapter)

*/int i2c_add_numbered_adapter(struct i2c_adapter *adap)

mutex_unlock(&core_lists);

if (status == -eagain)

goto retry;

if (status == 0)

status = i2c_register_adapter(adap);

return status;

}export_symbol_gpl(i2c_add_numbered_adapter);

/* 登出乙個i2c介面卡 */

int i2c_del_adapter(struct i2c_adapter *adap)

export_symbol(i2c_del_adapter);

/* 通過id號獲得i2c_adapter裝置結構體 */

struct i2c_adapter* i2c_get_adapter(int id)

export_symbol(i2c_get_adapter);

linux核心原始碼

1.機器當前使用的核心版本 apuser jianzhangubtnb uname a linux jianzhangubtnb 3.2.0 23 generic 36 ubuntu smp tue apr 10 20 39 51 utc 2012 x86 64 x86 64 x86 64 gnu ...

linux核心的idr學習 一

今天在看mtd驅動的時候發現idr,之後網上找了很多資料,其中我覺得這份參考資料比較好 idr主要是實現id與資料結構位址的繫結,一般是結構體的位址.如果位址比較少的情況下,可以直接定義乙個全域性的指標陣列,以陣列的下標作為id與位址對應.但是當位址數量很大的時候,固定的指標陣列無法滿足我們的需求,...

Linux核心原始碼目錄

linux核心原始碼目錄 1 arch architecture的縮寫,意思是架構,九鼎在做移植的時候就刪掉了。其他的目錄都跟你沒有任何的關係,所以你完全可以把他們刪除。2 block 英文是塊的意思,表示是塊裝置。以塊 多個位元組組成的整體,以塊為單位來整體訪問 比如說我們的sd卡,inand n...