普通字符设备驱动的两种注册方式(新&旧)
2016-08-28 08:32
274 查看
普通字符设备驱动的两种注册方式(新&旧)
在内核中,对于一个普通的字符设备驱动,不难发现有两种注册方式:register_chrdev族函数+创建设备类、文件的函数:这种方法是2.4版本流行的旧方法。优点是简单;缺点是无法指定次设备号
register_chrdev_region族+cdev族+创建设备类、文件的函数:这种方法是2.6版本推荐的新方法。优点是可以设置主次设备号;缺点是比较复杂
1.旧版本的注册方式
/*需要的定义*/ int test_major = -1; static struct class *mydev_pclass; #define TEST_NAME "test" #define MYDEV_CNT 3 /*正式注册*/ test_major = register_chrdev(0, TEST_NAME, &test_fops); if (test_major < 0) { printk(KERN_INFO "register test error\n"); goto out_err_0; } /*用class_create创建一个设备类,这是创建设备文件的前置任务*/ mydev_pclass = class_create(THIS_MODULE, "mydevice"); if (IS_ERR(mydev_pclass)) { //排错 printk(KERN_ERR "can't register device mydevice class\n"); goto out_err_1; } /*由device_create正式创建设备文件*/ device_create(mydev_pclass, NULL, MKDEV(test_major, 0), NULL, "mydevice"); return 0; /*倒影式错误处理流程*/ out_err_2: class_destroy(mydev_pclass); out_err_1: unregister_chrdev(test_major); out_err_0: return -EINVAL;
register_chrdev族函数是形成驱动设备的核心。register_chrdev的作用是申请并注册一个设备号、构建一个字符设备体、向内核注册此字符设备
register_chrdev函数的major参数可以设置主设备号,若major参数设为0则系统会自动分配一个设备号(这种做法比较可靠、方便)。register_chrdev的返回值就是分配到的主设备号,一般赋给一个全局变量来传递给unregister_chrdev注销函数,注销函数需要主设备号来作为参数
模块卸载函数内必须要包含unregister_chrdev函数,与这里的register_chrdev对应,只不过负责的是注销
最后由内核通知udev(即mdev)来创建一个位于/dev的设备文件。这一步其实是创建API与设备体之间的纽带,这样APP才能通过API操作设备文件(即调用 file_operations内的函数)。主要分为两步class_create先实例化新建一个设备类,然后由device_create正式创建设备文件
值得注意的是,创建设备文件的前提是系统开机时已经启动了udev(即mdev)功能。可以在/etc/init.d/rcS 或/etc/inittab中设置相关命令,详见手动构建rootfs及文件功能分析
关于错误处理,这里使用了内核中常见的goto方法。错误处理就是前面那些操作的逆操作,旨在发生错误时释放那些申请的资源,执行顺序必须符合“倒影式错误处理流程”
2.新版本的注册方式
/*需要用到的定义*/ #define MYDEV_NUM MKDEV(MYMAJOR, 0) #define MYNAME "mydevice" #define MYDEV_CNT 3 static struct cdev *mydev_pcdev; static struct class *mydev_pclass; dev_t mydev_num = 0; unsigned int mydev_major = 0; /*正式开始注册*/ /*让内核给我们自动分配设备号(主次设备号)*/ ret = alloc_chrdev_region(&mydev_num, 0, MYDEV_CNT, MYNAME); mydev_major = MAJOR(mydev_num); if (ret < 0) { printk(KERN_INFO "alloc_chrdev_region fail\n"); goto out_err_0; } printk(KERN_INFO "MAJOR %d\n", mydev_major); /*cdev_alloc实例化一个字符设备体。为cdev分配内存*/ mydev_pcdev = cdev_alloc(); /*填充cdev设备体。最主要是将file_operations填充进去*/ cdev_init(mydev_pcdev, &mydev_fops); /*将设备体与设备号绑定并向内核注册一个字符设备*/ ret = cdev_add(mydev_pcdev, MYDEV_NUM, MYDEV_CNT); if (ret) { printk(KERN_INFO "cdev_add error\n"); goto out_err_1; } /*用class_create创建一个设备类,这是创建设备文件的前置任务*/ mydev_pclass = class_create(THIS_MODULE, "mydevice"); if (IS_ERR(mydev_pclass)) { //排错 printk(KERN_ERR "can't register device mydevice class\n"); goto out_err_2; } /*由device_create正式创建设备文件*/ device_create(mydev_pclass, NULL, MYDEV_NUM, NULL, "mydevice"); return 0; /*倒影式错误处理流程*/ out_err_3: class_destroy(mydev_pclass); out_err_2: cdev_del(mydev_pcdev); out_err_1: unregister_chrdev_region(mydev_num, MYDEV_CNT); out_err_0: return -EINVAL;
关于分配主次设备号,register_chrdev_region是用户自定义设备号的申请。并且可以通过参数设置设备的个数(即次设备号) ,设备号是通过MKDEV这个宏获得,它可以通过主设备号和次设备号来计算设备号。其实更方便的做法是使用alloc_chrdev_region让内核给我们自动分配一个,这样就不会导致设备号之间重复。
利用cdev_alloc实例化一个字符设备体,为cdev分配内存 。使用cdev_alloc分配内存的好处是cdev_del时内核会为我们自动释放cdev占用的空间,而如果我们自己malloc的话就要自己释放了。
利用cdev_init填充cdev设备体 ,最主要是将file_operations填充进去。有的驱动里面是没用cdev_init()的,而是手动去填充,例如 mydev_pcdev-> owner = THIS_MODULE; mydev_pcdev-> ops = &mydev_fops; 说到底cdev_init()其实就相当于上面两句
利用cdev_add将设备体与设备号绑定,并向内核注册一个字符设备
最后由内核通知udev(即mdev)来创建一个位于/dev的设备文件。这一步其实是创建API与设备体之间的纽带,这样APP才能通过API操作设备文件(即调用 file_operations内的函数)。主要分为两步class_create先实例化新建一个设备类,然后由device_create正式创建设备文件
值得注意的是,创建设备文件的前提是系统开机时已经启动了udev(即mdev)功能。可以在/etc/init.d/rcS 或/etc/inittab中设置相关命令,详见手动构建rootfs及文件功能分析
关于错误处理,这里使用了内核中常见的goto方法。错误处理就是前面那些操作的逆操作,旨在发生错误时释放那些申请的资源,执行顺序必须符合“倒影式错误处理流程”
相关文章推荐
- 笔记二:字符设备之cdev方式注册字符驱动
- rtc驱动框架 与 新的字符设备驱动注册方式
- miscdevice.h----其它类型设备驱动的注册方式(转载)
- 字符设备驱动--- 数据结构 设备注册struct cdev , 注销
- linux 驱动程序 设备模块 设备号 设备文件创建 设备注册 字符驱动设备分析
- JDBC中注册驱动的两种方式及其使用
- 字符设备驱动查询方式读取按键值
- JDBC两种方式注册驱动
- 字符设备驱动笔记——中断方式按键驱动之代码(六)
- 字符设备驱动程序之中断方式的按键驱动
- 字符设备驱动学习笔记-----中断方式取得按键值
- Linux字符设备驱动对IO操作有三种方式
- CTDIY-2-字符设备驱动的注册
- 韦东山驱动视频笔记——1.字符设备驱动程序之查询方式的按键驱动程序
- 字符设备驱动2:易错点【注册 、 注销】
- 一个典型的字符设备驱动,带平台设备与驱动注册
- 字符设备驱动之按键处理一(查询方式的按键驱动程序)
- 字符设备驱动——申请设备号、注册字符设备
- 字符设备驱动笔记——查询方式按键驱动(三)
- linux下字符设备驱动的三种创建方式