天天看點

混雜裝置動态次裝置号分析【轉】

今天看驅動源碼時,發現一個MISC_DYNAMIC_MINOR宏,于是分析了一下核心源碼。先粘出源碼。在misc_register函數中,有如下語句:

if (misc->minor == MISC_DYNAMIC_MINOR) {
              int i = DYNAMIC_MINORS;
              while (--i >= 0)
                     if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
                            break;
              if (i<0) {
                     mutex_unlock(&misc_mtx);
                     return -EBUSY;
              }
              misc->minor = i;
       }
 
       if (misc->minor < DYNAMIC_MINORS)
              misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
       dev = MKDEV(MISC_MAJOR, misc->minor);
宏定義MISC_DYNAMIC_MINOR=255,DYNAMIC_MINORS=64。
misc_minors定義static unsigned char misc_minors[DYNAMIC_MINORS / 8];是一個char型的數組。代碼的關鍵是看懂(misc_minors[i>>3] & (1 << (i&7))) == 0。為了友善分析,本人寫了一個分析i與i&7的值的程式
#include <iostream.h>
void main()
{
       int i=64;
       int j;
       int l;
       while(--i>=0)
       {
              j=i>>3;
              l=1<<(i&7);
              cout<<"j's valule is: "<<j<<endl;
              cout<<"l's valule is: "<<l<<endl;
              cout<<"i's valule is: "<<i<<endl;
       }
}      

運作結果:

……

……

       基于以上運作結果我們可以看出:

j的值是從7遞減到0,j每減一個值,l的值循環一次出現128,64,32,16,8,4,2,1

i的值則是從63一直減到0。

是以我們可以得出以下幾個結論

1.       misc_minors[i>>3]這個char型數組有8個成員,每個成員是一個8位的數(因為j是從7減到0)

2.       (1 << (i&7))),當i減小1時,(1 << (i&7)))就向右移1位。即出現128,64,32,16,8,4,2,1的情況

3.       misc_minors數組成員與i值有對應關系,即misc_minors[7]對應63,62,61……56

misc_minors[6]對應55,54,……48。以些類推。因為misc_minors的成員是8位的數,每一個成員對應8個minors,是以很容易這樣聯想:misc_minors成員的每一位标記一個次裝置号(有沒有使用過)。

4.       (misc_minors[i>>3] & (1 << (i&7))) == 0意思就是将misc_minors數組中8個成員的每個成員的每一位周遊一遍,看是否為0

看懂了(misc_minors[i>>3] & (1 << (i&7))) == 0的意思後往下看,如果條件成立,就—i,如果是就将i賦給minor。這就說明,此前的聯想是正确的。位是0就代表沒有使用過這個次裝置号,位1是代表使用過這個次裝置号。是以在下面的代碼中還可以看到,如果得到了一個次裝置号後,就要馬上将代表這個次裝置号的位标記為1。但是使用MISC_DYNAMIC_MINOR這個宏有一個限制:你的次裝置号不會超過63。