华清远见嵌入式学习——day32字符设备驱动

【1】复习

    1. 内核模块
    
        -1- 模块的编写
        
            三要素: 
            
                入口    :module_init() --->>>  int  __init xxx(void);
                出口    :module_exit() --->>>  void __exit xxx(void);
                GPL声明 :MODULE_LICENSE("GPL")
        
            模块传参:
            
            include --->>> linux
            
                <linux/moduleparam.h>
                
                module_param()
                module_param_string()
                module_param_array()
            
            符号表导出:
        
                EXPORT_SYMBOL(sym)
                EXPORT_SYMBOL_GPL(sym)
        
        -2- 模块的编译
        
            内部编译
            外部编译
            动态编译
            静态编译
        
        -3- 模块的使用
        
            加载 --->>>  insmod  --->>> module_init注册的函数
            卸载 --->>>  rmmod   --->>> module_exit注册的函数

【2】作业

    
【一】、字符设备驱动重要结构体

    设备分类:
    
        1. 字符设备
        
            以字节流的形式进行数据读写
        
        2. 块设备
        
            存储设备
        
        3. 网络设备
        
            网卡

            
    [1]. 描述字符设备的结构体cdev

        <linux/cdev.h>
        
        struct cdev {
            struct module *owner;            //THIS_MODULE
            struct file_operations *ops;    //操作方法集
            dev_t dev;                        //设备号
            unsigned int count;                //设备计数    
        };


    [2]. 操作方法集 
    
        struct file_operations {
            struct module *owner;
            
            loff_t (*llseek) (struct file *, loff_t, int);
            
            /* read 接口 */
            ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
            /* write 接口 */
            ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
            /* poll接口 */
            unsigned int (*poll) (struct file *, struct poll_table_struct *);
            /* ioctl接口 */
            long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
            /* open 接口 */
            int (*open) (struct inode *, struct file *);
            /* release 接口*/
            int (*release) (struct inode *, struct file *);
            /* 异步通知接口 */
            int (*fasync) (int, struct file *, int);
        };

    [3]. 设备号 
    
        dev_t dev;  __u32 
        
        主设备和次设备号组成
        
        主设备号:高12bit
        
        MAJOR(dev_t dev)
        
        #define MINORBITS    20
        #define MAJOR(dev)    ((unsigned int) ((dev) >> MINORBITS))
        
        MINOR(dev_t dev)
        
        #define MINORMASK    ((1U << MINORBITS) - 1)
        #define MINOR(dev)    ((unsigned int) ((dev) & MINORMASK))
        
        MKDEV(int major,int minor)
        
    
【二】、字符设备驱动编写(重点)

    0. 申请设备号
    
        -1- 自动分配设备号
            /****************************************************************************
             *参数: 
             *            @dev            dev_t类型的指针
             *            @baseminor        次设备号的起始
             *            @count            设备个数
             *            @name            设备名
             *返回值:成功返回0,失败返回负数错误码
             ***************************************************************************/        
             int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
                        const char *name)
        
        -2- 手动指定设备号
            /****************************************************************************
             *参数: 
             *            @from        设备号   MKDEV(int major , int minor)
             *            @count        设备个数
             *            @name        设备名
             *返回值:成功返回0,失败返回负数错误码
             ***************************************************************************/            
             int register_chrdev_region(dev_t from, unsigned count, const char *name)        

             void unregister_chrdev_region(dev_t from, unsigned count)
             
    1. 分配cdev结构体
    
       /***************************************
        *参数:
        *        @void
        *返回值:成功返回cdev结构体指针,失败
        *         返回NULL
        **************************************/
        struct cdev *cdev_alloc(void)

    
    2. 初始化cdev结构体
    
        /**********************************************************************
         *参数: 
         *        @cdev    cdev结构体指针
         *        @fops   操作方法集指针
         *返回值:void
         *********************************************************************/
         void cdev_init(struct cdev *cdev, const struct file_operations *fops)
         
    3. 将cdev添加到内核中
        
        /***************************************************************
         *参数: 
         *            @p       cdev结构指针
         *            @dev    设备号
         *            @count    设备个数
         *返回值:成功返回0,失败返回负数错误码
         **************************************************************/
         int cdev_add(struct cdev *p, dev_t dev, unsigned count)
         void cdev_del(struct cdev *p)
         
         
【三】、字符设备驱动文件创建

    [1]. 通过命令创建设备文件
    
        mknod - make block or character special files
        
        mknod  NAME TYPE [MAJOR MINOR]
        
        TYPE : c 字符设备   b :块设备
        NAME : 设备文件名
        
    [2]. 通过udev守护进程创建
        
        class_create
        
        device_crete
    
        

    
[作业]:

    使用register_chrdev_region注册设备号
    
    
[附录]:

    结构体变量初始化:
    
    struct stu{
        int a;
        int b;
        int c;
    };
    
    struct stu stu1 = {1,2,3}; //全部初始化
    
    //部分初始化
    struct stu stu2 = {
        .a = 3,
        .c = 4,
    };    
    
    
    struct stu stu3;
    
    stu3.a = 10;        //结构体成员变量赋值
    stu3.c = 20;
    


    

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值