linux驱动学习笔记(2.5) scull_init_module
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/