zoukankan      html  css  js  c++  java
  • 字符设备驱动: register_chrdev和register_chrdev_region

    概述:

    register_chrdev与unregister_chrdev配对使用;

    /*register_chrdev = __register_chrdev_region (一次性256个子设备,这种固定模式不太好,不能比256更多子设备,所以后来开始废除这种模式)+ cdev_add*/

    /* unregister_chrdev =  __unregister_chrdev_region +  cdev_del*/

    register_chrdev_region和__register_chrdev_region 功能是一样的;

    unregister_chrdev_region和__unregister_chrdev_region功能是一样的;

    /*register_chrdev = __register_chrdev_region (一次性256个子设备,这种固定模式不太好,不能比256更多子设备,所以后来开始废除这种模式)+ cdev_add*/
    
    static inline int register_chrdev(unsigned int major, const char *name,
                      const struct file_operations *fops)
    {
        return __register_chrdev(major, 0, 256, name, fops);
    }
    
    
    /**
     * __register_chrdev() - create and register a cdev occupying a range of minors
     * @major: major device number or 0 for dynamic allocation
     * @baseminor: first of the requested range of minor numbers
     * @count: the number of minor numbers required
     * @name: name of this range of devices
     * @fops: file operations associated with this devices
     *
     * If @major == 0 this functions will dynamically allocate a major and return
     * its number.
     *
     * If @major > 0 this function will attempt to reserve a device with the given
     * major number and will return zero on success.
     *
     * Returns a -ve errno on failure.
     *
     * The name of this device has nothing to do with the name of the device in
     * /dev. It only helps to keep track of the different owners of devices. If
     * your module name has only one type of devices it's ok to use e.g. the name
     * of the module here.
     */
    int __register_chrdev(unsigned int major, unsigned int baseminor,
                  unsigned int count, const char *name,
                  const struct file_operations *fops)
    {
        struct char_device_struct *cd;
        struct cdev *cdev;
        int err = -ENOMEM;
    
        cd = __register_chrdev_region(major, baseminor, count, name);
        if (IS_ERR(cd))
            return PTR_ERR(cd);
        
        cdev = cdev_alloc();
        if (!cdev)
            goto out2;
    
        cdev->owner = fops->owner;
        cdev->ops = fops;
        kobject_set_name(&cdev->kobj, "%s", name);
            
        err = cdev_add(cdev, MKDEV(cd->major, baseminor), count);
        if (err)
            goto out;
    
        cd->cdev = cdev;
    
        return major ? 0 : cd->major;
    out:
        kobject_put(&cdev->kobj);
    out2:
        kfree(__unregister_chrdev_region(cd->major, baseminor, count));
        return err;
    }
    /* unregister_chrdev =  __unregister_chrdev_region +  cdev_del*/
    
    static inline void unregister_chrdev(unsigned int major, const char *name)
    {
        __unregister_chrdev(major, 0, 256, name);
    }
    
    
    /**
     * __unregister_chrdev - unregister and destroy a cdev
     * @major: major device number
     * @baseminor: first of the range of minor numbers
     * @count: the number of minor numbers this cdev is occupying
     * @name: name of this range of devices
     *
     * Unregister and destroy the cdev occupying the region described by
     * @major, @baseminor and @count.  This function undoes what
     * __register_chrdev() did.
     */
    void __unregister_chrdev(unsigned int major, unsigned int baseminor,
                 unsigned int count, const char *name)
    {
        struct char_device_struct *cd;
    
        cd = __unregister_chrdev_region(major, baseminor, count);
        if (cd && cd->cdev)
            cdev_del(cd->cdev);
        kfree(cd);
    }
    /*register_chrdev_region和__register_chrdev_region 功能是一样的;
    unregister_chrdev_region和__unregister_chrdev_region功能是一样的;*/

    /*
    * * register_chrdev_region() - register a range of device numbers * @from: the first in the desired range of device numbers; must include * the major number. * @count: the number of consecutive device numbers required * @name: the name of the device or driver. * * Return value is zero on success, a negative error code on failure. */ 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); } /** * unregister_chrdev_region() - return a range of device numbers * @from: the first in the range of numbers to unregister * @count: the number of device numbers to unregister * * This function will unregister a range of @count device numbers, * starting with @from. The caller should normally be the one who * allocated those numbers in the first place... */ 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)); } }
  • 相关阅读:
    模块化工具require 学习笔记
    学习Jade模板引擎
    通过border来实现各种三角符号
    使用vscode 编译 sass
    Javascript 运行机制
    Vue调试工具 vue-devtools
    MVVM框架
    通信类
    面向对象
    原型和原型链
  • 原文地址:https://www.cnblogs.com/mylinux/p/5520125.html
Copyright © 2011-2022 走看看