cdev

来源:互联网 发布:现货白银指标公式源码 编辑:程序博客网 时间:2024/06/05 02:05
一. 字符设备结构体
//include/linux/cdev.h
    struct cdev {  
        struct kobject kobj;        //kobject对象  
        struct module *owner;       //模块所有者  
        const struct file_operations *ops;  //文件操作函数集  
        struct list_head list;      //链表头  
        dev_t dev;                  //设备号  
        unsigned int count;         //引用次数  
    };  
    
二. 分配字符设备结构体
//fs/char_dev.c
    struct cdev *cdev_alloc(void)  
    {  
        struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);  //分配内存  
        if (p) {  
            INIT_LIST_HEAD(&p->list);  //初始化链表头
            kobject_init(&p->kobj, &ktype_cdev_dynamic);  //初始化kobject对象
        }  
        return p;  
    }  

三. 字符设备初始化
//fs/char_dev.c
    void cdev_init(struct cdev *cdev, const struct file_operations *fops)  
    {  
        memset(cdev, 0, sizeof *cdev);  //初始化cdev结构体  
        INIT_LIST_HEAD(&cdev->list);    //初始化链表头  
        kobject_init(&cdev->kobj, &ktype_cdev_default);  //初始化kobject对象  
        cdev->ops = fops;               //指定文件操作函数集  
    }
    
四. 添加字符设备
//fs/char_dev.c
    int cdev_add(struct cdev *p, dev_t dev, unsigned count)  
    {  
    int error;
    p->dev = dev;            //设置设备号
    p->count = count;        //设置引用次数
    error = kobj_map(cdev_map, dev, count, NULL,
             exact_match, exact_lock, p);
    if (error)
        return error;
    kobject_get(p->kobj.parent);
    return 0;
    }  

五. 删除字符设备
//fs/char_dev.c
    void cdev_del(struct cdev *p)  
    {  
        cdev_unmap(p->dev, p->count);  
        kobject_put(&p->kobj);  
    }  
    
六. 设备号的分配与释放

1.静态分配 register_chrdev_region
//fs/char_dev.c
    int register_chrdev_region(dev_t from, unsigned count, const char *name)        //参数:起始主设备号,设备个数,设备名  
    {  
        struct char_device_struct *cd;  
        dev_t to = from + count;  
        dev_t n, next;  
      
        for (n = from; n < to; n = next) {  
            next = MKDEV(MAJOR(n)+1, 0);  
            if (next > to)  
                next = to;  
            cd = __register_chrdev_region(MAJOR(n), MINOR(n),next - n, name);  
            if (IS_ERR(cd))  
                goto fail;  
        }  
        return 0;  
    fail:  
        to = n;  
        for (n = from; n < to; n = next) {  
            next = MKDEV(MAJOR(n)+1, 0);  
            kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));  
        }  
        return PTR_ERR(cd);  
    }  

2.动态分配 alloc_chrdev_region

    int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name)  
    {  
        struct char_device_struct *cd;  
        cd = __register_chrdev_region(0, baseminor, count, name);  
        if (IS_ERR(cd))  
            return PTR_ERR(cd);  
        *dev = MKDEV(cd->major, cd->baseminor);  
        return 0;  
    }  

 

3.释放设备号 unregister_chrdev_region

    void unregister_chrdev_region(dev_t from, unsigned count)  
    {  
        dev_t to = from + count;  
        dev_t n, next;  
      
        for (n = from; n < to; n = next) {  
            next = MKDEV(MAJOR(n)+1, 0);  
            if (next > to)  
                next = to;  
            kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));  
        }  
    }
注:
MAJOR(dev_t dev)           //获得主设备号
MINOR(dev_t dev)       //获得次设备号
MKDEV(int major,int minor) //通过主次设备号来生成dev_t  

七.例子
    #include <linux/fs.h>  
    #include <linux/module.h>  
    #include <linux/cdev.h>  
      
    int test_major;  
    dev_t test_dev;  
    struct cdev *my_cdev;  
      
    static int test_open(struct inode * inode, struct file * filp)  
    {  
        return 0;  
    }  
      
    static const struct file_operations test_fops = {   //操作函数集  
        .owner = THIS_MODULE,  
        .open  = test_open,  
    };  
      
    static int __init test_init(void)  
    {  
        int ret=0;  
        my_cdev=cdev_alloc();       //分配字符设备结构体  
      
        if(test_major){             //分配设备号  
            test_dev=MKDEV(test_major,0);  
            register_chrdev_region(test_dev,0,"test");  
        }  
        else{  
            ret=alloc_chrdev_region(&test_dev,0,0,"test");  
            test_major=MAJOR(test_dev);  
        }  
        cdev_init(my_cdev,&test_fops);  //初始化字符设备,捆绑操作函数集  
        cdev_add(my_cdev,test_dev,0);   //添加字符设备,捆绑主设备号  
        return ret;  
    }  
      
    static void __exit  test_exit(void)  
    {  
        cdev_del(my_cdev);  
        unregister_chrdev_region(MKDEV(test_major,0),0);  
    }  
      
    module_init(test_init);  
    module_exit(test_exit);  
    MODULE_LICENSE("GPL"); 
0 0
原创粉丝点击