在字符设备驱动模块加载函数中应实现设备号的申请和cdev的注册,而在卸载函数中应实现设备号的释放和cdev的注销。
int scull_init_module(void)
{
int result, i;
dev_t dev = 0;
/* [1]分配设备编号 */
if (scull_major) { /* 预先自己指定了主设备号 */
dev = MKDEV(scull_major, scull_minor); /* 利用主设备号,找到设备编号给方法1用 */
result = register_chrdev_region(dev, scull_nr_devs, "scull");
} else { /* 动态自己生成设备编号,然后再利用设备编号得到主设备号;
记住如果用这个方法那么就要后建设备文件了,因为不能提前知道主号
当然也可以利用ldd3书中提供的脚本,巨方便&&通用 */
result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs,
"scull");
scull_major = MAJOR(dev);
}
if (result < 0) {
printk(KERN_WARNING "scull: can't get major %d/n", scull_major);
return result;
}
/*[2]设备对象实例化*/
/*
* allocate the devices -- we can't have them static, as the number
* can be specified at load time
*/
scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);
if (!scull_devices) {
result = -ENOMEM;
goto fail; /* Make this more graceful */
}
memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev));
/* [3]在这里初始化设备用了2.6的新方法,在scull_setup_cdev里完成 */
/* Initialize each device. */
for (i = 0; i < scull_nr_devs; i++) {
scull_devices[i].quantum = scull_quantum; /* 可以根据自己insmod时传参
来自己改变量子和量子集(指针数组)的大小 */
scull_devices[i].qset = scull_qset;
init_MUTEX(&scull_devices[i].sem);
scull_setup_cdev(&scull_devices[i], i); /* 在分别完主设备编号后goto Tag002 设备注册 */
}
/* At this point call the init function for any friend device */
dev = MKDEV(scull_major, scull_minor + scull_nr_devs);
dev += scull_p_init(dev);
dev += scull_access_init(dev);
#ifdef SCULL_DEBUG /* only when debugging */
scull_create_proc();
#endif
return 0; /* succeed */
fail:
scull_cleanup_module();
return result;
}
module_init(scull_init_module); //insmod
module_exit(scull_cleanup_module); //rmmod