淺談linux內核中的位圖


位圖的定義

位圖法就是bitmap的縮寫,所謂bitmap,是用每一位來存放某種狀態,適用於大規模數據,但數據狀態又不是很多的情況。通常是用來判斷某個數據存不存在的。例如,要判斷一千萬個人的狀態,每個人只有兩種狀態:男人,女人,可以用0,1表示。那么就可以開一個int數組,一個int有32個位,就可以表示32個人。操作的時候可以使用位操作。

位圖也可以用來存儲系統在線/離線處理器,來支持CPU熱插拔;再比如,位圖在Linux內核等初始化過程中存儲已分配的中斷請求

位圖聲明

數據結構和示例

在這個數組里面,可以存儲 N * sizeof(int) * 8個數據,但是最大的數只能是N * sizeof(int)  * 8 - 1。假如,我們要存儲的數據范圍為0-15,則我們只需要使得N=1,這樣就可以把數據存進去。如下圖:

數據為【5,1,7,15,0,4,6,10】,則存入這個結構中的情況為:

位圖法在內核中的應用示例

內核既要分配唯一的PID還要對已經分配好的PID進行跟蹤。內核是使用了一個大的位圖,其中每個PID由一個比特標識。PID的值可通過對應比特在位圖中的位置計算而來。因此,分配一個空閑的PID,本質上就等同於尋找位圖中第一個值為0的比特,接下來將比特設置為1,反之釋放一個PID可通過將對應的比特從1切換為0實現。

這個思想很簡單,那么在實現上8個,我們知道可以用一個能表示8種情況的整數來標識。一個字節的空間就有8個比特位。如0x03說明分配了的PID號是0,1號。

一般應用中數值范圍是很大的,如果數值是大於8,那該如何呢?首先可以考慮用一個大點的數來表示,如用unsigned long,這是表示四字節,一個unsigned long的整數可以表示的PID號范圍是0~31,要是PID號是大於31的又該如何設計呢?

我們可以申請一個連續的地址空間來表示。如:unsigned long bitmap[8]; 這申請了32個字節的連續地址空間,可以表示的范圍是0~32*8-1。如果申請的的PID號是在0~31的范圍,則只用處於首地址的數來表示即可。同理如果PID號范圍是在32~63,則用第二個地址的數來表示。以此類推。那么在具體實現上是怎么樣的呢?

PID號與所求的數據的地址存在着數學關系,我們要把這種關系弄清楚。PID號就是對應於偏移號,即從首個比特開始算起,看是偏移了幾位,偏移了的數值就是PID號。如第二個比特位,偏移了1位,所以PID號是1。而unsigned long數據類型,是占四個字節空間,即意味着一個地址可以表示32位表比特。所以第一個地址表示的偏移號是0~31,第二個地址表示的偏移號是32~63,第三個地址表示的偏移號是64~127,通過分析我們可以發現這樣的數學關系:0~31的任何數除以32都得0,表示是首地址,32~63的任何數除以32結果得1,表示是第二個地址,64~127的任何數除以32都得2,表示是第三個地址的數據。因此我們可以概括出其中的數學關系:偏移號除以32所得結果是相對於首地址的偏移地址量,得到偏移地址量后加上首地址可求出實際的地址,有了地址就可知道該地址上的數了。有了該數就可對它在相應位上置 位。

特定架構的位運算

clear_bit;

set_bit;

兩個函數來實現設置位的操作和清除位操作。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM