zoukankan      html  css  js  c++  java
  • 实验四

    本章内容:
    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
      
  • 相关阅读:
    通过设置P3P头来实现跨域访问COOKIE
    随心所欲玩复制 详解robocopy
    MySQL的mysqldump工具的基本用法
    uvm_void 寂静的空宇
    Chisel语言
    IP-XACT IP IEEE交换格式
    SystemC简介
    ( 转)UVM验证方法学之一验证平台
    (转)让你彻底理解:静态时序分析
    (转)存储芯片入门漫谈
  • 原文地址:https://www.cnblogs.com/zhuohua/p/7905725.html
Copyright © 2011-2022 走看看