看完了 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