位圖的定義
位圖法就是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;
兩個函數來實現設置位的操作和清除位操作。