Linux那些事兒之我是Block層(2)註冊一個塊設備驅動

看完了 block 子系統的初始化之後 , 我曾一度迷茫過 , 也曾輾轉反側 , 也曾苦惱萬分 , 我完全不知道下一步該怎麼走 , 幾經思索 , 思索着我和中國的未來 , 徘徊過後 , 彷徨過後 , 終於決定 , scsi disk 驅動同步進行往下走 , 因爲 scsi disk 那邊會調用許多 block 層這邊提供的函數 , 於是我們就在這邊來看看這些函數究竟是幹什麼的 .

第一個函數當然就是 register_blkdev().

     55 int register_blkdev(unsigned int major, const char *name)

     56 {

     57         struct blk_major_name **n, *p;

     58         int index, ret = 0;

     59

     60         mutex_lock(&block_subsys_lock);

     61

     62         /* temporary */

     63         if (major == 0) {

     64                 for (index = ARRAY_SIZE(major_names)-1; index > 0; index--) {

     65                         if (major_names[index] == NULL)

     66                                 break;

     67                 }

     68

     69                 if (index == 0) {

     70                          printk("register_blkdev: failed to get major for %s/n",

     71                                name);

     72                         ret = -EBUSY;

     73                         goto out;

     74                 }

     75                  major = index;

     76                 ret = major;

     77         }

     78

     79         p = kmalloc(sizeof(struct blk_major_name), GFP_KERNEL);

     80         if (p == NULL) {

     81                 ret = -ENOMEM;

     82                 goto out;

     83         }

     84

     85         p->major = major;

     86         strlcpy(p->name, name, sizeof(p->name));

     87         p->next = NULL;

     88         index = major_to_index(major);

     89

     90         for (n = &major_names[index]; *n; n = &(*n)->next) {

     91                 if ((*n)->major == major)

     92                         break;

     93         }

     94         if (!*n)

     95                 *n = p;

     96         else

     97                 ret = -EBUSY;

     98

     99         if (ret < 0) {

    100                 printk("register_blkdev: cannot get major %d for %s/n",

    101                        major, name);

    102                 kfree(p);

    103         }

    104 out:

    105         mutex_unlock(&block_subsys_lock);

    106         return ret;

    107 }

sd 那邊調用這個函數來看 , 咱們是指定了主設備號了的 . 換言之 , 這裏的 major 是非零值 , struct blk_major_name 的定義也在 block/genhd.c :

     27 static struct blk_major_name {

     28         struct blk_major_name *next;

     29         int major;

     30         char name[16];

     31 } *major_names[BLKDEV_MAJOR_HASH_SIZE];

注意這裏順便定義了一個數組 major_names, 咱們這裏也用到了 .

這其中 BLKDEV_MAJOR_HASH_SIZE 定義於 include/linux/fs.h:

    1575 #define BLKDEV_MAJOR_HASH_SIZE  255

即數組 major_names[] 255 個元素 , 換言之 , 咱們定義了 255 個指針 .

88 行這個內聯函數同樣來自 block/genhd.c:

     33 /* index in the above - for now: assume no multimajor ranges */

     34 static inline int major_to_index(int major)

     35 {

     36         return major % BLKDEV_MAJOR_HASH_SIZE;

     37 }

比如咱們傳遞的 major 8, 那麼 major_to_index 就是 8.

不難理解 ,register_blkdev() 這個函數做的事情就是 , 爲這 255 個指針找到歸屬 . 即先在 79 行調用 kmalloc 申請一個 struct blk_major_name 結構體並且讓 p 指向它 , 接下來爲 p 賦值 , n 將指向 major_names[index], 比如 index 就是 8, 那麼 n 就指向 major_names[8], 一開始它肯定爲空 , 所以直接執行 94 行並進而 95 , 於是就把賦好值的 p 的那個結構體賦給了 major_names[8], 因此 ,major_names[8] 就既有 major 也有 name ,name 就是 ”sd”.

那麼此時此刻的效果是什麼 ? 告訴你 , 不是在 /dev/ 目錄下面有 sda,sdb 之類的文件 , 而是通過 /proc/devices 能夠看到這個塊設備驅動註冊了 .

localhost:/usr/src/linux-2.6.22.1 # cat /proc/devices

Character devices:

  1 mem

  2 pty

  3 ttyp

  4 /dev/vc/0

  4 tty

  4 ttyS

  5 /dev/tty

  5 /dev/console

  5 /dev/ptmx

  7 vcs

  10 misc

  13 input

  21 sg

  29 fb

128 ptm

136 pts

162 raw

180 usb

189 usb_device

254 megaraid_sas_ioctl

 

Block devices:

  1 ramdisk

  3 ide0

  7 loop

  8 sd

  9 md

  65 sd

  66 sd

  67 sd

  68 sd

  69 sd

  70 sd

  71 sd

128 sd

129 sd

130 sd

131 sd

132 sd

133 sd

134 sd

135 sd

253 device-mapper

254 mdp

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章