zoukankan      html  css  js  c++  java
  • 《Linux4.0设备驱动开发详解》笔记第六章:Linux字符设备驱动

    6.1 linux字符设备驱动结构

    6.1.1 cdev结构体

    • cdev结构体描述一个字符设备
    struct cdev { 
            struct kobject kobj; //内嵌的kobject对象
            struct module *owner;   //所属模块 
            const struct file_operations *ops;//文件操作结构
            struct list_head list; 
            dev_t dev;          //设备号,int 类型
            unsigned int count; 
    }; 
    • cdev的dev_t成员定义了设备号,高12位为主设备号,低20位为次设备号
      • 获取主、次设备号:
        • MAJOR(dev_t dev)
        • MINOR(dev_t dev)
      • 主次设备号生成dev_t:MKDEV(int major,int minor)
    • cdev结构体相关的操作函数
    void cdev_init(struct cdev *, const struct file_operations *);//建立cdev和file_operation之间的连接
    struct cdev *cdev_alloc(void); //动态申请一个cdev内存 
    void cdev_put(struct cdev *p);   //释放 
    int cdev_add(struct cdev *, dev_t, unsigned);  //注册设备
    void cdev_del(struct cdev *);//注销设备

    6.1.2 分配和释放设备号

    • 在注册设备之前应该先申请设备号
      • register_chrdev_region()用于已知设备号
      • register_chrdev_region()用于动态申请
    int register_chrdev_region(dev_t from,unsigned count,const char *name)
    
    int alloc_chrdev_region(dev_t *dev,unsigned baseminor,unsigned count,const char *name)
    • 释放设备号
    void unregister_chrdev_region(dev_t from,unsigned count)
    • 注册与注销字符设备顺序关系如下:
    register_chrdev_region()-->cdev_add()     //此过程在加载模块中 
    cdev_del()-->unregister_chrdev_region()     //此过程在卸载模块中

    6.1.3 字符设备驱动组成

    • 字符设备的模块加载与卸载函数
    • 字符设备驱动的file_operation结构体中的成员函数,大多数实现以下函数
      • read()
      • write()
      • ioctl()
    • copy_from_user():用户空间缓冲区到内核空间
    • copy_to_user():内核空间到用户空间缓冲区
      • 返回0:成功
      • 返回正数:不能被复制的字节数
      • 负数:操作失败
    • 复制的内容是简单的类型,如int、char、long等,则可以用以下函数
      • put_user、get_user
      • 上述函数中_user是一个宏,表示其后的指针指向用户空间
    • 内核空间访问用户空间缓存时需要合法性检查
      • access_ok(type, add, size):确认缓存区确实属于用户空间
    • ioctl函数
      • 设备类型字段为一个幻数,可以使0-0xff的值,内核中的ioctl-number.txt有推荐的已经存在的幻数,新设备区应该避免与其冲突
      • 方向字段表示数据传输的方向
        • _IOC_NONE:无数据传输
        • _IOC_READ:读
        • _IOC_WRITE:写
        • _IOC_READ|_IOC_WRITE:双向
    设备类型 序列号 方向 数据尺寸
    8位 8位 2位 13/14位
    • 预定义命令:内核中预定了一些I/O控制命令,如果某设备中抱哈没了与预定义命令一样的命令码,则这些命令会作为预定义命令被内核处理而不是被设备驱动处理

      • FIOCLEX:通知内核当exec()系统调用发生时,自动关闭打开的文件
      • FIONCLEX:与FIOCLEX相反,清除由FIOCLEX命令设置的标志
      • FIOQSIZE:获得一个文件和目录的大小,当用于设备文件时返回一个ENOTTY错误
      • FIONBIO:修改在filp->f_flags中的O_NONBLOCK标志
  • 相关阅读:
    Codeforces Round #311 (Div. 2)题解
    firefox 被劫持hao123 主页
    国有航空为啥“放下身段”读春秋?
    ORACLE中常见SET指令
    最大概率法分词及性能測试
    怎样利用JDBC连接并操作Oracle数据库
    hdu5240
    代码调试过程中easy遇到的问题
    最简单的基于FFmpeg的AVDevice样例(读取摄像头)
    FPGA 功耗结构设计
  • 原文地址:https://www.cnblogs.com/zcjboke/p/5513135.html
Copyright © 2011-2022 走看看