module_init(scull_init_module);
驱动程序中第一个运行的函数:scull_init_module
但我们执行命令insmod scull.ko, 即开始运行如下的函数完成模块的初始化。
模块初始化都要完成那些功能呢?
1.完成设备号的注册。
设备号分为两部分,主设备号与次设备号。
其中主设备号通常标识设备对应的驱动程序,此设备号由内核使用,用于正确确定设备文件所指的设备。
具体的操作,我们可以通过指定或动态申请的方法来获得设备编号。建议使用动态。
2.搞定设备编号之后,作为一个字符设备是对字符设备结构体cdev的初始化以及一些因为功能需要而做的初始化;
针对自身的应用模块定义了一个结构体
struct scull_dev {
struct scull_qset *data; /* Pointer to first quantum set */ //用于存储数据的内存块链表头
int quantum; /* the current quantum size */
int qset; /* the current array size */ //对链表中的数据块大小做一个限制;
unsigned long size; /* amount of data stored here */ //计量使用的内存个数
unsigned int access_key; /* used by sculluid and scullpriv */
struct semaphore sem; /* mutual exclusion semaphore */ //定义一信号量,用于搞同步
struct cdev cdev; /* Char device structure */ //字符设备结构体
};
看这个没太理解,先想想scull的“机制”与“策略”;
所谓机制就是:需要提供什么功能;
所谓策略就是:如何使用这些功能。
scull是一个演示程序,这是目的;
他需要提供的功能是我们使用正常的系统调用接口函数访问它。如open read write lseek
scull是在内核中的一个内存块;它可以让我们像对其他设别一样,打开关闭,响应我们的读操作,写操作,定位操作,及设置操作,且数据不会丢失。
想到这点我们再看如上结构体scull_dev 。
int scull_init_module(void)
{
int result, i;
dev_t dev = 0;
/*
* Get a range of minor numbers to work with, asking for a dynamic
* major unless directed otherwise at load time.
*/
if (scull_major) { //指定设备编号,来注册
dev = MKDEV(scull_major, scull_minor);
result = register_chrdev_region(dev, scull_nr_devs, "scull");
} else { //动态申请设备编号
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;
}
/*
* 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));
/* Initialize each device. */
for (i = 0; i < scull_nr_devs; i++) {
scull_devices[i].quantum = scull_quantum;
scull_devices[i].qset = scull_qset;
//init_MUTEX(&scull_devices[i].sem);
sema_init(&scull_devices[i].sem,1);
scull_setup_cdev(&scull_devices[i], i); //初始化字符设备结构体了,这是公务,就像唐僧每到一个地方要换通关文牒似的
}
//###到这 明天继续
/* 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;
}
欢迎阅读其它文章,一起交流:http://www.cnblogs.com/fly-fish/