当前位置:嗨网首页>书籍在线阅读

16-vmem_disk驱动模块的加载与卸载

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

13.7.2 vmem_disk驱动模块的加载与卸载

vmem_disk驱动的模块加载函数完成的工作与13.3节给出的模板完全一致,它支持“制造请求”(对应代码清单13.9)、请求队列(对应代码清单13.10)两种模式(留意在请求队列方面又支持简、繁两种模式),使用模块参数request_mode进行区分。代码清单13.16给出了vmem_disk设备驱动的模块加载与卸载函数。

代码清单13.17 vmem.disk设备驱动的模块加载与卸载函数

1 static int __init vmem_disk_init(void)

2 {

3 int i;

4 /*

5 * 注册块设备

6 */

7 vmem_disk_major = register_blkdev(vmem_disk_major, "vmem_disk");

8 if (vmem_disk_major <= 0) {

9 printk(KERN_WARNING "vmem_disk: unable to get major number\n");

10 return -EBUSY;

11 }

12 /*

13 * 分配设备数组,初始化它们

14 */

15 Devices = kmalloc(ndevices*sizeof (struct vmem_disk_dev), GFP_KERNEL);

16 if (Devices == NULL)

17 goto out_unregister;

18 for (i = 0; i < ndevices; i++)

19 setup_device(Devices + i, i);

20

21 return 0;

22

23 out_unregister:

24 unregister_blkdev(vmem_disk_major, "sbd");

25 return -ENOMEM;

26 }

27

28 static void vmem_disk_exit(void)

29 {

30 int i;

31

32 for (i = 0; i < ndevices; i++) {

33 struct vmem_disk_dev *dev = Devices + i;

34

35 del_timer_sync(&dev->timer);

36 if (dev->gd) {

37 del_gendisk(dev->gd);

38 put_disk(dev->gd);

39 }

40 if (dev->queue) {

41 if (request_mode == RM_NOQUEUE)

42 kobject_put (&dev->queue->kobj);

43 else

44 blk_cleanup_queue(dev->queue);

45 }

46 if (dev->data)

47 vfree(dev->data);

48 }

49 unregister_blkdev(vmem_disk_major, "vmem_disk");

50 kfree(Devices);

51 }

52

53 /*

54 * 设置设备

55 */

56 static void setup_device(struct vmem_disk_dev *dev, int which)

57 {

58 /*

59 * 分配globalmem的内存

60 */

61 memset (dev, 0, sizeof (struct vmem_disk_dev));

62 dev->size = nsectors*hardsect_size;

63 dev->data = vmalloc(dev->size);

64 if (dev->data == NULL) {

65 printk (KERN_NOTICE "vmalloc failure.\n");

66 return;

67 }

68 spin_lock_init(&dev->lock);

69

70 /*

71 * 使用一个timer来模拟设备invalidate

72 */

73 init_timer(&dev->timer);

74 dev->timer.data = (unsigned long) dev;

75 dev->timer.function = vmem_disk_invalidate;

76

77 /*

78 * I/O队列,具体实现依赖于我们是否使用make_request函数

79 */

80 switch (request_mode) {

81 case RM_NOQUEUE:

82 dev->queue = blk_alloc_queue(GFP_KERNEL);

83 if (dev->queue == NULL)

84 goto out_vfree;

85 blk_queue_make_request(dev->queue, vmem_disk_make_request);

86 break;

87

88 case RM_FULL:

89 dev->queue = blk_init_queue(vmem_disk_full_request, &dev->lock);

90 if (dev->queue == NULL)

91 goto out_vfree;

92 break;

93

94 default:

95 printk(KERN_NOTICE "Bad request mode %d, using simple\n", request_mode);

96

97 case RM_SIMPLE:

98 dev->queue = blk_init_queue(vmem_disk_request, &dev->lock);

99 if (dev->queue == NULL)

100 goto out_vfree;

101 break;

102 }

103 blk_queue_hardsect_size(dev->queue, hardsect_size);

104 dev->queue->queuedata = dev;

105 /*

106 * gendisk分配与初始化

107 */

108 dev->gd = alloc_disk(vmem_disk_MINORS);

109 if (! dev->gd) {

110 printk (KERN_NOTICE "alloc_disk failure\n");

111 goto out_vfree;

112 }

113 dev->gd->major = vmem_disk_major;

114 dev->gd->first_minor = which*vmem_disk_MINORS;

115 dev->gd->fops = &vmem_disk_ops;

116 dev->gd->queue = dev->queue;

117 dev->gd->private_data = dev;

118 snprintf (dev->gd->disk_name, 32, "vmem_disk%c", which + 'a');

119 set_capacity(dev->gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE));

120 add_disk(dev->gd);

121 return;

122

123 out_vfree:

124 if (dev->data)

125 vfree(dev->data);

126 }

上述代码中引用的vmem_disk_major、ndevices、nsectors、hardsect_size都是模块参数,其默认值定义如下:

static int vmem_disk_major = 0;

module_param(vmem_disk_major, int, 0);

static int hardsect_size = 512;

module_param(hardsect_size, int, 0);

static int nsectors = 1024; / 该驱动器的大小 /

module_param(nsectors, int, 0);

static int ndevices = 4;

module_param(ndevices, int, 0);

/*

  • 我们能使用的不同request模式

*/

enum {

RM_SIMPLE = 0, / 简单请求函数(对应代码清单13.13) /

RM_FULL = 1, / 复杂的请求函数(对应代码清单13.15) /

RM_NOQUEUE = 2, / 使用make_request(对应代码清单13.16) /

};

static int request_mode = RM_SIMPLE;

module_param(request_mode, int, 0);

在模块加载时我们可以更改这些参数。尤其值得注意的是,request_mode等于RM_SIMPLE、RM_FULL、RM_NOQUEUE分别对应于代码清单13.13、13.15和13.16这三种不同的请求处理方式。