【嵌入式系统复习总结】第五章 嵌入式 Linux 驱动开发

文章目录

前情提要

本人是一名大三学生,由于期末复习需要,所以按照老师的ppt总结整理此笔记,希望对你有所帮助

第五章 嵌入式 Linux 驱动开发

  1. 设备驱动的概念、抽象层次、分类、特点、安装方法
  2. 设备驱动开发过程
  3. 字符设备驱动结构,file_operations 里常用的接口函数、驱动的结构
  4. 所有的函数不需要背

1) 设备驱动的概念、抽象层次、分类、特点、安装方法

设备驱动程序介于操作系统和硬件之间,屏蔽了硬件设备的物理细节,并提供了访问各种硬件设备的统一接口。Linux内核源程序中占有60%以上。

应用程序 库 内核 驱动程序之间的关系

什么是驱动程序:
  1. 作为操作系统的一部分(OS = Kernel + Device Driver)
    • 向上为Linux系统提供访问硬件统一调用接口
    • 向下用于控制硬件:与Arm裸机程序一样,通过读写硬件寄存器达到控制硬件的目的
  2. 驱动程序的运行是被动的
    • 驱动只是告诉内核"我在这里,我能做这些工作":向内核注册
    • 这些工作何时开始,取决于应用程序:应用触发驱动
设备驱动分类
  1. 字符设备驱动
    设备以字节流 方式访问(以字节为单位读写)
    字符设备驱动实现了open、close 、read、write 等系统调用
    应用程序通过设备文件 (如/dev/ttySAC0)访问设备
    字符设备文件的第一个标志是前面的"c"标志。

    $ ls --l /dev
    crw-rw---- 1 root uucp 4, 64 08-30 22:58 ttyS0 /串口设备, c表示字符设备/
    crw-rw---- 1 root uucp 3, 4 08-30 22:58 ttyS0 /* 主设备号3,此设备号4 */

  2. 块设备驱动

设备上的数据以块的方式存放 (如NAND Flash上的数据以页为单位)

块设备驱动程序也向用户层提供open、close

应用通过设备文件 (如/dev/sda1)来访问设备

块设备驱动特别之处:

(1)操作硬件的实现方式不一样:先将数据组织成块,再操作设备

(2)数据块上的数据按照一定的格式组织:存放文件系统,实现mount

例如,在系统中的块设备IDE硬盘的主设备号是3,而多个IDE硬盘及其各个分区分别赋予次设备号1、2、3......

$ ls --l /dev
brw-r-----  1 root  floppy 2,   0 08-30 22:58 fd0/*软盘设备,b表示块设备*/
  1. 网络设备驱动
    设备上的数据以不固定大小的帧 输入与输出
    没有/dev上对应的设备文件,不通过open、read、write操作
    系统为网络设备访问分配唯一接口(如eth0)
    为应用层提供一套数据包传输函数访问接口(SOCKET)

2) 设备驱动开发过程

  1. 查看原理图、数据手册,了解设备的操作方法
  2. 在内核中找到相近的驱动程序,以它为模板开发
  3. 实现驱动程序的初始化,并向内核注册
  4. 按照内核规定的驱动框架,实现相关操作函数(如open、read、write)
  5. 编译 驱动程序到内核中 ,或者编译成模块并挂载(insmod)到内核
直接编译进内核
  1. 将驱动模块源码合入内核源码

    • 设备驱动程序应包含在drivers子目录
    • 首先确认是否存在于设备驱动程序特性相似的目录名
    • 存在则插入相应目录,否则字符类型插入char目录,块类型插入block目录,网络类型插入net目录
  2. 修改内核编译选项文件

    • Linux内核支持使用内核编译选项包含到内核中的功能
    • make menuconfig读入这些内核编译选项文件来配置内核
    • 2.6内核编译选项文件为KConfig
    • 进入加入了驱动模块的目录,修改目录下的KConfig,使得加入的驱动能在配置项中显示
  3. 修改内核源码中的Makefile

    • Makefile指定了驱动程序的编译规则,使得驱动程序能包含到内核image中
    • Makefile根据make menuconfig配置设定的编译条件变量,决定是要把特定源代码编译成模块还是包含到内核中,或者是清除。
    • 进入合入了驱动模块的目录,修改改目录下的Makefile,使得合入的驱动源码能编译进内核
  4. 确认合入内核的驱动在内核启动时自动运行

    • 重新编译并启动新内核,dmesg=>确认"hello world"已打印出来
    • 带**__int标志**的函数被放入初始化代码段,内核会依次调用初始化代码段的
    • 函数,并在初始化完成后释放 init 区段.
编译成模块
  1. 模块加载函数(必需)

    安装模块时被系统自动调用的函数,通过module_init宏来指定

  2. 模块卸载函数(必需)

    卸载模块时被系统自动调用的函数,通过module_exit宏来指定

加载 insmod (insmod hello.ko)

卸载 rmmod (rmmod hello)

查看 lsmod

加载 modprobe (modprobe hello)

modprobe 如同 insmod, 也是加载一个模块到内核。它的不同

之处在于它会根据/lib/modules/<$version>/modules.dep

来查看要加载的模块, 看它是否还依赖于其他模块,如果是,

modprobe 会首先找到这些模块, 把它们先加载到内核。

3) 字符设备驱动结构,file_operations 里常用的接口函数、驱动的结构

总体结构:

3、调用关系

(1)当应用程序使用open打开某个设备(/dev的设备文件)

设备驱动程序file_operations结构中open成员函数被调用

(2)当应用程序使用使用read、write、ioctl等函数读写、控制设备

设备驱动程序file_operations结构中read、write、ioctl等成员函数被调用

4、字符设备驱动程序目的

为具体硬件设备file_operations 结构实现操作设备所需的成员函数

5、设备文件与驱动程序file_operations结构的对应关系

主设备号用来标识 与设备文件相连 的驱动程序,次编号 背驱动程序来辨别操作的是那个设备
主设备号 用来反映设备类型
次设备号 用来区分同类型的设备

6、设备驱动注册

在驱动中init 函数中实现的。

c 复制代码
      //老注册接口
      register_chrdev(DEV_MAJOR, DEV_NAME, &dev_ops); 

     //2.6内核使用cdev来描述一个字符设备
     cdev_init(&s_cdev, &dev_ops); //初始化cdev		
     ret = cdev_add(&s_cdev, s_dev, DEV_COUNT); //注册cdev

注册完成后,应用程序操作设备文件时,系统就会根据

主设备号找到内核中注册file_operations结构

驱动程序举例:

字符驱动程序框架

  1. 包含头文件
    编写字符驱动程序时需要的内核头文件
  2. 定义常量
    定义模块的主设备号和名称,它们将在字符设备的初始化的注册函数中使用。
  3. 函数声明
    声明需要使用的函数,将被注册到文件操作数据结构struct file_operations中。
  4. 文件操作数据结构的指针
c 复制代码
static struct file_operations virtual_char_fops={
	owner:         THIS_MODULE,
	llseek:          virtual_char_llseek,
	read:            virtual_char_read,
	write:           virtual_char_write,
	ioctl:            virtual_char_ioctl,
	open:           virtual_char_open,
	release:        virtual_char_close,
}

这是驱动程序的核心部分,定义了一个静态文件操作数据结构,将数据结构中几个成员赋值为驱动程序中函数的指针

5. 函数中的各种操作
   - module_init()注册的函数执行设备文件的注册
   - module_exit()注册的函数执行设备文件的卸载。
   - open中增加引用计数;close中减少引用计数。
   - write/read中执行定义的读写操作,内容传递主要通过缓冲区的指针buf。
   - ioctl中执行驱动程序自定义的命令,根据cmd选择要执行的命令
  1. 应用程序
    linux的应用程序与驱动程序调用关系

应用程序使用驱动程序主要有以下几个步骤:

  1. 使用open打开设备文件
  2. 在使用驱动程序的时候,根据需要调用write/read/ioctl等操作
  3. 使用close关闭设备文件

4) 所有的函数不需要背

相关推荐
IT果果日记12 分钟前
ubuntu 安装 conda
linux·ubuntu·conda
Python私教15 分钟前
ubuntu搭建k8s环境详细教程
linux·ubuntu·kubernetes
羑悻的小杀马特28 分钟前
环境变量简介
linux
__基本操作__1 小时前
历遍单片机下的IIC设备[ESP--0]
单片机·嵌入式硬件
小陈phd1 小时前
Vscode LinuxC++环境配置
linux·c++·vscode
是阿建吖!1 小时前
【Linux】进程状态
linux·运维
明明跟你说过2 小时前
Linux中的【tcpdump】:深入介绍与实战使用
linux·运维·测试工具·tcpdump
Komorebi.py3 小时前
【Linux】-学习笔记05
linux·笔记·学习
Mr_Xuhhh3 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
亦枫Leonlew3 小时前
微积分复习笔记 Calculus Volume 1 - 6.5 Physical Applications
笔记·数学·微积分