• 实验四


    本章内容:
    Linux设备驱动的基本概念
    Linux设备驱动程序的基本功能
    linux设备驱动的运作过程
    常见设备驱动接口函数
    掌握LCD设备驱动程序编写步骤
    掌握键盘设备驱动程序编写步骤

    1. 设备驱动简介

      • 设备驱动程序是内核的一部分。
      • OS通过各种驱动程序来操作硬件设备,设备驱动程序是内核的一部分,硬件驱动程序是OS最基本的组成部分。
      • Linux将最基本的核心代码编译在内核当中,其他代码编译到内核或者内核的模块文件,需要时再加载。常见的内核模块驱动程序比如声卡和网卡,linux基础驱动包括CPU,PCI总线,TCP/IP协议,APM(高级电源管理)等。
      • 加载驱动就是加载内核模块。
      • lsmod列出当前系统中加载的模块
      • 设备驱动程序与外界的接口
      • 【驱动与接口】
      • 设备驱动程序必须为内核或者其子系统提供一个标准接口。
    2. 设备驱动编程

      • 设备驱动程序以模块的方式动态加载到内核中。在驱动开发时没有main()函数,模块在调用insmod命令时被加载,在该函数中完成设备的注册。调用rmmod命令时被卸载。设备完成注册加载后,用户的应用程序可以对该设备进行一定的操作,如open()、read()、write()等。
    3. 字符设备的注册

      • 在内核中使用struct cdev结构来描述字符设备,我们在驱动设备中将已分配到的设备号以及设备操作接口(struct file_operations结构)赋予struct cdev结构变量。
      • 使用cdev_alloc()函数向系统申请分配struct cdev结构,再用cdev_init()函数初始化已分配到的结构与file_operations结构关联。
      • 调用cdev_add()函数将设备号与struct cdev结构进行关联并向内核正式报告新设备的注册,新设备可以使用了。
    4. 设备驱动结构函数

      • 打开设备的函数接口open()
      • 释放设备的函数接口realease()
      • 读写设备read() write()函数
      #include <linux/fs.h>
      
      ssize_t (*read) (struct file *filp, char *buff, size_t count, loff_t *offp)  
      ssize_t (*write) (struct file *filp, const char *buff, size_tc count, loff_t *offp)
      //*filep文件指针,buff指向用户缓冲区,count传入数据长度,offp用户在文件中的位置
      //返回值:写入的数据长度
      
      
      • 实现用户空间与内核空间数据交换的函数copy_to_user()copy_from_user(),同时检查用户空间指针是否有效,如无效,不进行复制。
      #include <asm/uaccess.h>
      unsigned long copy_to_user(void *to, const void *from, unsigned long count)
      unsigned long copy_from_user(void *to, const void *from, unsigned long count)
      
      //to数据目的缓冲区,from数据源缓冲区,count数据长度
      //返回值:写入的数据长度。失败:EFAULT
      
      
      • 硬件配置和控制,ioctl()函数接口给用户提供对设备的非读写操作机制。
      #include <linux/fs.h>
      int (*ioctl) (sturct inode *inode, sturct file *filp,unsigned int cmd, unsigned long arg)
      //inode:文件的内核内部结构指针,filp:文件描述符,cmd命令类型,arg命令相关参数
      
      • 以字节为单位分配内存的函数kmalloc()
      #include <linux/malloc.h>
      void *kmalloc(unsigned int len, int flags)
      //len:希望申请的字节数
      //flags:GFP_KERNEL,GFP_BUFFER,GFP_ATOMIC,GFP_USER,GFP_HIGHUSER,__GFP_DMA,__GFP_HIGHMEN
      //成功:写入的数据长度。
      //失败:-EFAULT
      
      • 以页面为单位分配内存的函数:get_free_page()
      #include <linux/malloc.h>
      unsigned long get zeroed_page(int flags)
      unsigned long __get_free_page(int flags)
      unsigned long __get_free_page(int flags, unsigned long order)
      unsigned long __get_dma_page(int flags, unsigned long order)
      //order:要请求的页面数,以2为底的对数
      //成功:返回指向新分配的页面的指针
      //失败:-EFAULT
      
      • 打印信息printk()与printf()类似。
      #include <linux/kernel>
      int printk(const char *fmt,……)
      //fmt:日志级别
      //……:同printf,比如%d,%x
      //成功:0
      //失败:-1
      
  • 相关阅读:
    yocto/bitbake 学习资源
    QEMU/KVM学习资源
    ubuntu 中创建和删除用户
    git 重命名本地和远程分支
    Ubuntu 上搭建 FTP 服务器
    gdb 常见用法
    git log 显示与特定文件相关的 commit 信息
    基于 qemu system mode 运行 arm 程序
    基于 qemu user mode 运行 aarch64 程序
    checking in(airport)
  • 原文地址:https://www.cnblogs.com/zhuohua/p/7905725.html
Copyright © 2020-2023  润新知