seuge

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

驱动模块需要完成的功能:

  • 注册设备
  • 添加文件操作函数与ops结构绑定

注册设备的具体过程是先向系统申请一个设备号,可以注册一个特定的设备号也可以由系统动态分配。一般使用动态分配,但是添加模块的过程只是向/proc/devices文件中添加了设备的信息,最后还得从从devices文件中cat 出设备的设备号,然后在手动在/dev中添加设备,mknod /dev/key c N 0。访问设备就是通过/dev 的文件进行访问的,访问过程通过设备号找到设备关联的驱动程序,设备号是架起设备和驱动之间的桥梁。也可以在模块内部直接完成/dev 里设备添加的过程 ,调用函数device_create(..)。

有了设备号还不行,还得创建一个设备,可以用cdev结构也可以自己定义一个设备结构然后把cdev结构嵌入进自己的设备结构。有了设备和设备号就得用这个设备号初始化这个设备,然后再把这个设备添加到设备链表。

初始化的过程就是对设备结构的成员变量进行赋值。(网上的代码,出处http://www.cnblogs.com/nick123/archive/2010/03/26/1696966.html#commentform)

1 int err;
2 cdev_init(buttons_cdev_p,&tq2440_buttons_fops);
3 buttons_cdev_p->owner = THIS_MODULE;
4 buttons_cdev_p->ops = &tq2440_buttons_fops;
5 err = cdev_add(buttons_cdev_p,dev_num,1);
6 if(IS_ERR(&err))
7    printk(KERN_NOTICE "Error %d adding buttons",err);

 

下面是整个驱动模块的初试化过程。

 1 static int __init tq2440_buttons_init(void)
 2  {
 3      int ret;
 4   
 5   
 6        if(BUTTON_MAJOR)   //手动分配设备号
 7              {  
 8                dev_num=MKDEV(BUTTON_MAJOR, BUTTON_MINOR);              ret=register_chrdev_region(dev_num,DEV_COUNT,DEVICE_NAME);
 9              }
10       else  {          //动态分配设备号
11           ret = alloc_chrdev_region(&dev_num,BUTTON_MINOR,DEV_COUNT,DEVICE_NAME);        
12       }
13       if(ret<0)     {
14                   printk(DEVICE_NAME " can't register major number \n");
15                   return ret;
16           }
17       /*动态申请cdev结构体的内存*/
18       buttons_cdev_p = kmalloc(sizeof(struct cdev),GFP_KERNEL);
19       if(!buttons_cdev_p)   //申请失败
20           {
21               ret = -ENOMEM;
22               goto fial_malloc;
23           }
24       memset(buttons_cdev_p,0,sizeof(struct cdev));
25       int err;
26       cdev_init(buttons_cdev_p,&tq2440_buttons_fops);
27       buttons_cdev_p->owner = THIS_MODULE;
28       buttons_cdev_p->ops = &tq2440_buttons_fops;
29       err = cdev_add(buttons_cdev_p,dev_num,1);
30       if(IS_ERR(&err))
31       printk(KERN_NOTICE "Error %d adding buttons",err);
32       //注册一个类,使mdev可以在"/dev/"目录下面
33       //建立设备节点
34       button_class = class_create(THIS_MODULE,DEVICE_NAME);
35       if(IS_ERR(button_class))
36           {
37           printk("Error:Failed to creat button_class \n");
38           return -1;
39           }
40       //创建一个设备节点,节点名为DEVICE_NAME
41       
42       device_create(button_class,NULL,dev_num,NULL,DEVICE_NAME);
43       printk(DEVICE_NAME " initialized \n");
44       return 0;
45       fial_malloc:unregister_chrdev_region(dev_num, 1);
46   }

驱动注销的过程:

由于注册的过程显示分配了设备号,定义了设备结构体,并且注册了设备。所以注销的过程相应的得,注销设备,释放内存结构体,释放设备号。

1  static void __exit tq2440_buttons_exit(void)
2   {
3       cdev_del(buttons_cdev_p);//注销cdev
4       kfree(buttons_cdev_p);//释放设备结构体内存
5       unregister_chrdev_region(dev_num,DEV_COUNT);//释放设备号
6   
7  }

以上就是一个驱动模块的基本框架。主要的编码工作是编写文件操作函数,或者如果用到中断的话还有中断的注册,中断函数。

posted on 2012-04-24 21:38  seuge  阅读(429)  评论(0)    收藏  举报