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/
 
posted @ 2011-09-01 23:16  夏大王  阅读(601)  评论(0编辑  收藏  举报