Linux那些事儿之我是Block层(2)注册一个块设备驱动
2008-01-31 09:10
417 查看
看完了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
第一个函数当然就是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
相关文章推荐
- Linux那些事儿之我是Block层(2)注册一个块设备驱动
- Linux那些事儿之我是Block层(2)注册一个块设备驱动
- Linux那些事儿之我是Block层(2)注册一个块设备驱动
- linux 驱动程序 设备模块 设备号 设备文件创建 设备注册 字符驱动设备分析
- linux iic驱动编程之二 向总线注册设备(2)
- Linux关于总线、设备、驱动的注册顺序
- linux中platform总线解析(四)(platform设备注册后自动匹配驱动)
- linux 下platform设备和驱动注册的先后顺序
- 【转】Linux那些事儿之我是U盘(9)总线,设备,和驱动(下)
- linux注册设备驱动的理解
- linux驱动设备号的注册
- linux的几种设备驱动的数据结构和驱动注册之块设备_hantown-ChinaUnix博客
- Linux(2.6.35.7)字符设备驱动注册接口
- Linux那些事儿之我是U盘(8)总线,设备,和驱动(上)
- 迅为Linux驱动教程——总线_设备_驱动注册流程详解
- [笔记分享] [OS] Linux设备模型之驱动注册
- linux驱动---字符设备的注册register_chrdev说起
- linux-i2c驱动 之 i2c设备层的注册过程probe函数如何被调用分析
- 迅为Linux驱动教程——总线_设备_驱动注册流程详解
- Linux驱动编程 step-by-step (四) 字符设备的注册与设备节点的自动创建