linux驅動開發--字元裝置:建立一組裝置節點
www.edpli.com
為裝置驅動支援多個裝置個體做準備,針對cdev進行改進
将代表字元裝置的cdev對象包含在裝置驅動定義的私有資料結構體中
對裝置驅動私有資料結構體采用核心記憶體配置設定方式為其配置設定記憶體
将為每個裝置添加cdev對象和建立裝置節點封裝為一個獨立函數
支援多個裝置個體
為裝置驅動支援多個裝置個體對驅動進行改進
循環調用為每個裝置添加cdev對象和建立裝置節點而封裝的獨立函數實作在系統中添加對多個裝置個體的支援
[objc]view plaincopy
- /**
- *Copyright (c) 2013.TianYuan
- *All rights reserved.
- *
- *檔案名稱: char_device_driver06.c
- *檔案辨別: 支援多裝置:建立10個裝置節點檔案,操作函數還需修改
- *#測試: cat /dev/cdd0
- *目前版本:1.0
- *作者:wuyq
- *取代版本:xxx
- *原作者:xxx
- *完成日期:2013-11-26
- */
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/cdev.h>
- #include <linux/device.h>
- #include <linux/slab.h>
- MODULE_LICENSE("GPL");
- #define CDD_MAJOR 200//cat /proc/devices找一個尚未使用的
- #define CDD_MINOR 0
- #define CDD_COUNT 10
- dev_t dev = 0;
- u32 cdd_major = 0;
- u32 cdd_minor = 0;
- structclassclass *dev_class = NULL;
- struct cdd_cdev{
- struct cdev cdev;
- structdevice *dev_device;
- u8 led;
- };
- structcdd_cdev *cdd_cdevp = NULL;
- int cdd_open(struct inode* inode, structfile *filp)
- {
- structcdd_cdev *pcdevp = NULL;
- printk("enter cdd_open!\n");
- pcdevp = container_of(inode->i_cdev, struct cdd_cdev, cdev);
- printk("led = %d\n", pcdevp->led);
- return0;
- }
- int cdd_read(structfile *filp, char__user *buf, size_t count, loff_t *offset)
- printk("enter cdd_read!\n");
- int cdd_write(structfile *filp, constchar__user *buf, size_t count, loff_t *offset)
- printk("enter cdd_write!\n");
- int cdd_ioctl(structinode *inode, structfile *filp, unsigned int cmd, unsigned long data)
- printk("enter cdd_ioctl!\n");
- int cdd_release(structinode *inode, structfile *filp)
- printk("enter cdd_release!\n");
- struct file_operations cdd_fops = {
- .owner = THIS_MODULE,
- .open = cdd_open,
- .read = cdd_read,
- .write = cdd_write,
- .ioctl = cdd_ioctl,
- .release = cdd_release,
- };
- int __init cdd_init(void)
- int ret = 0;
- int i = 0;
- if(cdd_major){
- dev = MKDEV(CDD_MAJOR, CDD_MINOR);//生成裝置号
- //注冊裝置号;1、要注冊的起始裝置号2、連續注冊的裝置号個數3、名字
- ret = register_chrdev_region(dev, CDD_COUNT, "cdd_demo");
- }else{
- // 動态配置設定裝置号
- ret = alloc_chrdev_region(&dev, cdd_minor, CDD_COUNT, "cdd_demo02");
- }
- if(ret < 0){
- printk("register_chrdev_region failed!\n");
- goto failure_register_chrdev;
- //擷取主裝置号
- cdd_major = MAJOR(dev);
- printk("cdd_major = %d\n", cdd_major);
- cdd_cdevp = kzalloc(sizeof(struct cdd_cdev)*CDD_COUNT, GFP_KERNEL);
- if(IS_ERR(cdd_cdevp)){
- printk("kzalloc failed!\n");
- goto failure_kzalloc;
- /*建立裝置類*/
- dev_class = class_create(THIS_MODULE, "cdd_class");
- if(IS_ERR(dev_class)){
- printk("class_create failed!\n");
- goto failure_dev_class;
- for(i=0; i<CDD_COUNT; i++){
- /*初始化cdev*/
- cdev_init(&(cdd_cdevp[i].cdev), &cdd_fops);
- /*添加cdev到核心*/
- cdev_add(&(cdd_cdevp[i].cdev), dev+i, 1);
- /* “/dev/xxx” */
- device_create(dev_class, NULL, dev+i, NULL, "cdd%d", i);
- cdd_cdevp[i].led = i;
- failure_dev_class:
- kfree(cdd_cdevp);
- failure_kzalloc:
- unregister_chrdev_region(dev, CDD_COUNT);
- failure_register_chrdev:
- return ret;
- void __exit cdd_exit(void)
- /*逆序消除*/
- for(; i < CDD_COUNT; i++){
- device_destroy(dev_class, dev+i);
- cdev_del(&(cdd_cdevp[i].cdev));
- //cdev_del(&((cdd_cdevp+i)->cdev));
- class_destroy(dev_class);
- }
- module_init(cdd_init);