• 字符设备驱动程序


    在内核中,dev_t类型用来保存设备编号——包括主设备号和次设备号。
    内核内部使用struct cdev结构来表示字符设备。

    根据设备编号获取主设备号和次设备号

    MAJOR(dev_t dev);			//获取主设备号
    MINOR(dev_t dev);			//获取次设备号
    

    根据主设备号和次设备号得到设备编号

    MKDEV(int major, int minor);
    

    分配和释放设备编号

    int register_chrdev_region(dev_t from, unsigned count, const char *name);
    /*
     *	在主设备号确定的情况下使用
     *from:		要分配的设备编号范围的起始值,主要是有一个确定的主设备号,次设备号一般为0。
     *count:	所请求的连续设备编号的个数(次设备号的个数)
     *name:		将出现在/proc/devices和sysfs中
     */
    int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name);
    /*
     *	动态分配主设备号
     *dev:		输出参数,将动态分配好的首个设备号返回。
     *baseminor:	第一个次设备号的编号,一般为0。
     */
    void unregister_chrdev_region(dev_t from, unsigned count);
    

    inode数据结构中有类型为dev_t的i_rdev字段,当inode指向的是设备文件时,它描述的是设备编号。
    从inode数据结构中获得主设备号和次设备号

    unsigned int iminor(struct inode* inode);
    unsigned int imajor(struct inode* inode);
    

    字符设备的注册

    struct cdev *cdev_alloc(void);		                    //函数原型
    struct cdev *my_cdev = cdev_alloc();
    my_cdev->owner = THIS_MODULE;
    
    void cdev_init(struct cdev *cdev, struct file_operation * fops);	//函数原型
    my_cdev->ops = &my_fops;  或者: cdev_init(my_cdev, &my_fops);
    
    int cdev_add(struct cdev* cdev, dev_t num, unsigned int count);		//函数原型
    /*
     *count:	是应该和该设备关联的设备编号的数量,常取1.
     */
    cdev_add(my_cdev, devno, 1);
    
    void cdev_del(struct cdev *dev);		              //函数原型
    cdev_del(my_cdev);
    

    早期的接口
    注册字符设备驱动程序的接口

    int register_chardev(unsigned int major, const char *name, struct file_operation *fops);	//函数原型
    /*
     *major:	设备的主设备号。
     *name:		驱动程序的名称,出现在/proc/devices中
     */
    实现方法:
    {
      __register_chrdev(major, 0, 256, name, fops);{		//major, baseminor, count, name, fops
        __register_chrdev_region(major, baseminor, count, name);{
          //注册设备编号,若传入的major为0,则自动分配
        }
        cdev = cdev_alloc();
        cdev->owner = fops->owner;
        cdev->ops = fops;
        cdev_add(cdev, MKDEV(cd->major, baseminor), count);
      }
    }
    

    移除设备驱动程序的接口

    int unregister_chrdev(unsigned int major, const char *name);		//函数原型
    实现方法:
    {
      __unregister_chrdev(major, 0, 256, name);{
        __unregister_chrdev_region(major, baseminor, count);{
          //释放前面分配设备编号时申请的空间。
        }
        cdev_del(cd->cdev);
      }
    }
    

      

  • 相关阅读:
    java实现万年历
    java中关于Calendar
    java中各种类型的输入输出
    java(向上向下转型)
    MyEclipse还原默认窗口
    Hibernate映射问题之OneToOne【自己整理】
    Neither BindingResult nor plain target object for bean
    剑宗与气宗
    分治算法
    spring处理线程并发
  • 原文地址:https://www.cnblogs.com/hei-da-mi/p/6062391.html
Copyright © 2020-2023  润新知