Linux驱动程序设计.ppt
合集下载
Chap6-11 Linux设备驱动程序ppt课件
BSP开发的一般步骤如下:
硬件主板研制,测试 操作系统的选定,BSP编程 上层应用程序的开发
最新版整理ppt
13
编写BSP函数
BSP对板卡中每个芯片的操作都通过多个函数 来完成
如果应用程序对板卡的操作都直接通过调用 BSP中的函数来完成,那将很不利于源程序的 调试 ,并降低了程序的可移植性
设备的打开与释放
open() release()
设备的读写操作
read() write()
设备的控制操作
ioctl()
最新版整理ppt
35
设备驱动的加载
使用模块的方式动态加载驱动
int func_init(void) Makefile: insmod xx.o lsmod rmmod xx.o
而是在系统初始化过程中由BSP把它们与操作系 统中通用的设备驱动程序关联起来,并在随后的 应用中由通用的设备驱动程序调用,实现对硬件 设备的操作。
最新版整理ppt
12
BSP开发的前提和步骤
开发的前提 :
熟悉硬件方面:使用CPU等 熟悉工具方面:电表,示波器,逻辑分析仪,
硬件仿真器,仿真调试环境等 语言方面:汇编语言,C语言
8
初始化过程
片级初始化:
主要完成CPU的初始化
设置CPU的核心寄存器和控制寄存器 CPU核心工作模式 CPU的局部总线模式等
片级初始化把CPU从上电时的缺省状态逐步设置 成为系统所要求的工作状态
这是一个纯硬件的初始化过程
最新版整理ppt
9
初始化过程(续1)
板级初始化:
完成CPU以外的其他硬件设备的初始化 同时还要设置某些软件的数据结构和参数,为随后
最新版整理ppt
硬件主板研制,测试 操作系统的选定,BSP编程 上层应用程序的开发
最新版整理ppt
13
编写BSP函数
BSP对板卡中每个芯片的操作都通过多个函数 来完成
如果应用程序对板卡的操作都直接通过调用 BSP中的函数来完成,那将很不利于源程序的 调试 ,并降低了程序的可移植性
设备的打开与释放
open() release()
设备的读写操作
read() write()
设备的控制操作
ioctl()
最新版整理ppt
35
设备驱动的加载
使用模块的方式动态加载驱动
int func_init(void) Makefile: insmod xx.o lsmod rmmod xx.o
而是在系统初始化过程中由BSP把它们与操作系 统中通用的设备驱动程序关联起来,并在随后的 应用中由通用的设备驱动程序调用,实现对硬件 设备的操作。
最新版整理ppt
12
BSP开发的前提和步骤
开发的前提 :
熟悉硬件方面:使用CPU等 熟悉工具方面:电表,示波器,逻辑分析仪,
硬件仿真器,仿真调试环境等 语言方面:汇编语言,C语言
8
初始化过程
片级初始化:
主要完成CPU的初始化
设置CPU的核心寄存器和控制寄存器 CPU核心工作模式 CPU的局部总线模式等
片级初始化把CPU从上电时的缺省状态逐步设置 成为系统所要求的工作状态
这是一个纯硬件的初始化过程
最新版整理ppt
9
初始化过程(续1)
板级初始化:
完成CPU以外的其他硬件设备的初始化 同时还要设置某些软件的数据结构和参数,为随后
最新版整理ppt
chap61嵌入式Linux驱动程序开发 1 ppt课件
ssize_t (*readv) (struct file *, const
struct iovec *, unsigned long, loff_t
*);
ssize_t (*writev) (struct file *, const
struct iovec *, unsigned long, loff_t
CPU响应中断是有条件的,如内部允许中断、中断未 被屏蔽、当前指令执行完等。
CPU响应中断以后,就会中止当前的程序,转去执行 一个中断服务子程序,以完成为相应设备的服务。
2020/12/22
9
3.直接访问内存(DMA)方式
DMA可允许设备和系统内存间在没有处理器参与 的情况下传输大量数据。
设备驱动程序在利用DMA之前,需要选择DMA 通道并定义相关寄存器,以及数据的传输方向,即 读取或写入,然后将设备设定为利用该DMA通道 传输数据。
2020/12/22
int (*fsync) (struct file *, struct
dentry *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct
file_lock *);
对设备初始化和释放; 对设备进行管理,包括实时参数设置,以及提供对设 备的操作接口; 读取应用程序传送给设备文件的数据或者回送应用程 序请求的数据; 检测和处理设备出现的错误。
2020/12/22
11
Linux设备驱动程序
Linux操作系统将所有的设备全部看成文件,并通过文 件的操作界面进行操作。对用户程序而言,设备驱动程序 隐藏了设备的具体细节,对各种不同设备提供了一致的接 口,一般来说,是把设备映射为一个特殊的设备文件。
第四章 Linux驱动程序设计.ppt
printk(KERN_ALERT " Hello world exit\n"); } module_init(hello_init); module_exit(hello_exit);
模块初始化 宏
模块卸载宏
2019年12月24日
21
打印调试printk
指示日志级别的宏 KERN_EMERG 用于紧急事件消息,一般是系统崩溃前提示<0>
块设备通过位于 /dev 目录的文件系统结点来存取
块设备和字符设备的区别仅仅在于内核内部管理数据的 方式
块设备有专门的接口,块设备的接口必须支持挂装 (mount)文件系统。
应用程序一般通过文件系统来访问块设备上的内容
2019年12月24日
17
4-2设备的分类和特点
网络设备特点
简单的内核模块编译(内核2.6)
如果是多个源文件编译出一个模块,假设模块名是test.ko, 那么源文件名不能有test.c
obj-m := test.o
test-objs := file1.o file2.o file3.o
KDIR := /home/at9200/kernel/linux-2.6.38/
(4)应用程序得到文件描述符后,使用库提供的write 或ioclt函数发出控制命令 (5)库根据write或ioclt函数传入的参数执行“swi”指令, 这条指令会引起CPU异常,再次进入内核 (6)内核的异常处理函数根据参数调用驱动程序的相关 函数,控制硬件
4-2设备的分类和特点
块设备特点
static int __init hello_init(void) {
printk(KERN_ALERT "Hello world\n");
模块初始化 宏
模块卸载宏
2019年12月24日
21
打印调试printk
指示日志级别的宏 KERN_EMERG 用于紧急事件消息,一般是系统崩溃前提示<0>
块设备通过位于 /dev 目录的文件系统结点来存取
块设备和字符设备的区别仅仅在于内核内部管理数据的 方式
块设备有专门的接口,块设备的接口必须支持挂装 (mount)文件系统。
应用程序一般通过文件系统来访问块设备上的内容
2019年12月24日
17
4-2设备的分类和特点
网络设备特点
简单的内核模块编译(内核2.6)
如果是多个源文件编译出一个模块,假设模块名是test.ko, 那么源文件名不能有test.c
obj-m := test.o
test-objs := file1.o file2.o file3.o
KDIR := /home/at9200/kernel/linux-2.6.38/
(4)应用程序得到文件描述符后,使用库提供的write 或ioclt函数发出控制命令 (5)库根据write或ioclt函数传入的参数执行“swi”指令, 这条指令会引起CPU异常,再次进入内核 (6)内核的异常处理函数根据参数调用驱动程序的相关 函数,控制硬件
4-2设备的分类和特点
块设备特点
static int __init hello_init(void) {
printk(KERN_ALERT "Hello world\n");
Linux下设备管理与驱动程序编写实例ppt(共66页)
unsigned int(*poll)(struct file *,struct poll_table_struct *); int (*ioctl)(struct inode *,struct file *,unsigned int ,unsigned long ); int (mmap)(struct file *,struct vm_area_struct *); int (*open)(struct inode *,struct file *); int (*flush)(struct file*); int(*release)(struct inode *,struct file *);
第11章 设备管理
Linux和其他操作系统一样,支持众多 的、各式各样的外接设备。
但是,面对层出不穷的新硬件产品,必 须有人不断编写新的驱动程序,以便让这些 设备能够在 Linux 下正常工作,从这个意义 上讲,讲述驱动程序的编写就是一件非常有 意义的工作。
本章也涉及到Linux下设备管理的原则和 方法。
llseek(): 重新定位读、写位置,需要提供 偏移量参数。
flush(): 清除内容。
release(): 关闭设备,并释放资源等。
mmap(): 将设备内存映射到进程地址空间。 通常只有块设备驱动程序使用。
11.2.3 常用函数原型
1. 设备操作函数原形 struct file_operations {
2.向系统注册的函数原形 int register_chrdev(unsigned int major,const char * name,struct file_operations * fops) { if (major = = 0 ) {
linux设备驱动程序开发课件(PPT 81页)
ARM及Thumb指令集
TM
19
19
驱动程序中涉及的几个概念
设备驱动程序的设备号和入口点
Linux 系统通过设备号来区分不同设备。设备号由两部分组 成:主设备号和次设备号。
主设备号标识设备对应的驱动程序。系统中不同的设备可以 有相同的主设备号,主设备号相同的设备使用相同的驱动程 序。
次设备号用来区分具体驱动程序的实例。一个主设备号可能 有多个设备与之对应,这多个设备正是在驱动程序内通过次 设备号来进一步区分的。次设备号只能由设备驱动程序使用 ,内核的其他部分仅将它作为参数传递给驱动程序。
两个数字对应 主设备号和次 设备号
TM
21
21
ARM及Thumb指令集
在/proc/devices 中列出了系统中处 于活动状态设备的 主设备号
TM
22
22
dev_t类型
dev_t类型
内核用dev_t类型来保存设备编号,dev_t是个32位的数,12位 表示主设备号,20为表示次设备号。在实际使用中,是通过中 定义的宏来转换格式。
在/proc/devices 中列出了系统中处于活动状态设备的主设备 号,所谓的活动状态是指与该设备对应的设备驱动已经被系 统内核装载。
ARM及Thumb指令集
TM
20
20
字符为c表示字 符设备,为b表 示块设备
ARM及Thumb指令集
/dev/
对于现有Linux 操作 系统,/dev 目录是必不 可少的,这个目录包含 了所有Linux 系统所知 道的字符设备,块设备 和网络设备
读取应用程序传送给设备文件的数据或者回送应用程序请求 的数据;
检测和处理设备出现的错误。
ARM及Thumb指令集
嵌入式Linux驱动程序开发PPT课件
• 查询环节
– 寻址状态口 – 读取状态寄存器的标志位 – 若不就绪就继续查询,直至就绪
• 传送环节
– 寻址数据口 – 是输入,通过输入指令从数据口读入数据 – 是输出,通过输出指令向数据口输出数据
输入状态
N 就绪? Y 数据交换
第10页/共32页
8D
输入
锁存器
设备
+5V
D RQ
-STB
8位 三态 缓冲器
•服务结束后,又返回原 来的断点,继续执行原 来的程序
主程序
中断服务程序 入口
中断请求
程序 断点
提 供 服 务
为 外 设
继
续
执 返回断点
行
第13页/共32页
中断传送是一种效率更高的程序传送方式 进行传送的中断服务程序是预先设计好的 中断请求是外设随机向CPU提出的 CPU对请求的检测是有规律的:在每条指令 的最后一个时钟周期采样中断请求输入引脚
• I/O处理机——CPU委托专门的I/O处理机来管理 外设,完成传送和相应的数据处理
第1页/共32页
1、 无条件传送方式及其接口
• 在CPU与慢速变化的设备交换数据时,可以认为 它们总是处于“就绪”状态,随时可以进行数据 传送,这就是无条件传送,或称立即传送、同步 传送
• 适合于简单设备,如LED 数码管、按键/按纽等 • 无条件传送的接口和操作均十分简单 • 这种传送有前提:外设必须随时处于就绪状态
• CPU出让系统总线(输出高阻),由DMA控制器 (DMAC)接管系统总线
第17页/共32页
传送过程: ⑴ CPU对DMA控制器进行初始化设置 ⑵ 外设、DMAC、CPU, 3者通过应答信号建立联系:CPU将总线暂交
linux驱动21页PPT
内核和网络驱动程序间的通讯完全不同于内核和字符设备以及 块设备驱动程序之间的通信,内核调用一套和数据包传输相关 的函数。
设备文件和设备驱动
设备文件和设备驱动
设备文件是文件系统上的一个 节点,是一种特殊的文件,叫 做设备文件。每个设备文件在 用户空间代表了一个设备。
设备文件一般存在/dev目录下, 用mknod命令创建。
/proc/ioports:查看设备的IO端口。 /proc/interrupts:查看正在使用的中断号。
构造和运行模块
Kernel Module的特点
模块只是预先注册自己以便服务于将来的某个请求,然后就立即 结束。
模块可以是实现驱动程序,文件系统,或者其他功能。 加载模块后,模块运行在内核空间,和内核链接为一体。
#include <linux/module.h>
int init_module(void) {
printk("<1>Hello, world\n"); return 0; } void cleanup_module(void) { printk("<1>Goodbye world\n"); }
简单的内核模块例子(2)
SUMMER TEMPLATE
linux驱动
Linux Kernel 系统架构图
设备驱动程序简介
驱动程序的特点
是应用和硬件设备之间的一个软件层 。
这个软件层一般在内核中实现
设备驱动程序的作用在于提供机制,而不是提供策略, 编写访问硬件的内核代码时不要给用户强加任何策略
○ 机制:驱动程序能实现什么功能。
1version>/modules.dep文件,其中<kernel version>
设备文件和设备驱动
设备文件和设备驱动
设备文件是文件系统上的一个 节点,是一种特殊的文件,叫 做设备文件。每个设备文件在 用户空间代表了一个设备。
设备文件一般存在/dev目录下, 用mknod命令创建。
/proc/ioports:查看设备的IO端口。 /proc/interrupts:查看正在使用的中断号。
构造和运行模块
Kernel Module的特点
模块只是预先注册自己以便服务于将来的某个请求,然后就立即 结束。
模块可以是实现驱动程序,文件系统,或者其他功能。 加载模块后,模块运行在内核空间,和内核链接为一体。
#include <linux/module.h>
int init_module(void) {
printk("<1>Hello, world\n"); return 0; } void cleanup_module(void) { printk("<1>Goodbye world\n"); }
简单的内核模块例子(2)
SUMMER TEMPLATE
linux驱动
Linux Kernel 系统架构图
设备驱动程序简介
驱动程序的特点
是应用和硬件设备之间的一个软件层 。
这个软件层一般在内核中实现
设备驱动程序的作用在于提供机制,而不是提供策略, 编写访问硬件的内核代码时不要给用户强加任何策略
○ 机制:驱动程序能实现什么功能。
1version>/modules.dep文件,其中<kernel version>
第一章Linux设备驱动简介.pptx
移除连接
嵌入式Linux的设备管理
Linux将设备分成两大类:一类是块设备,类似磁盘以记录块或扇区为单位,成块 进行输入/输出的设备;另一类是字符设备,类似键盘以字符为单位,逐个进行输入/ 输出的设备。网路设备是介于块设备和字符设备之间的一种特殊设备。
块设备接口仅支持面向块的I/O操作,所有I/O操作都通过在内核地址空间中的I/O 缓冲区进行,它可以支持随机存取的功能。文件系统通常都建立在块设备上。
• YAFFS (Yet Another Flash File System)
• ROMFS
• RAMFS • JFFS2(Journaling Flash File System)
• 设备控制
– 几乎每一个系统操作都会映射到物理设备上 – 除去CPU,内存以及其他几个很有限的对象之外,几乎所有
的设备控制操作都由与被控制设备相关的代码(设备驱动程 序)来完成
查询方式白白浪费了大量的处理器时间,而中断方式才是多任务操作系统中最有效利 用处理器的方式。当CPU进行主程序操作时,外设的数据已存入端口的数据输入寄存器, 或端口的数据输出寄存器已空,此时由外设通过接口电路向CPU发出中断请求信号。 CPU在满足一定条件下,暂停执行当前正在执行的主程序,转入执行相应能够进行输入/ 输出操作的子程序,待输入/输出操作执行完毕之后,CPU再返回并继续执行原来被中断 的主程序。这样,CPU就避免了把大量时间耗费在等待、查询外设状态的操作上,使其工 作效率得以大大提高。中断方式的原理示意图如图6.1所示。
字符设备接口支持面向字符的I/O操作,由于它们不经过系统的快速缓存,所以它 们负责管理自己的缓冲区结构。字符设备接口只支持顺序存取的功能,一般不能进行 任意长度的I/O请求,而是限制I/O请求的长度必须是设备要求的基本块长的倍数。
嵌入式Linux的设备管理
Linux将设备分成两大类:一类是块设备,类似磁盘以记录块或扇区为单位,成块 进行输入/输出的设备;另一类是字符设备,类似键盘以字符为单位,逐个进行输入/ 输出的设备。网路设备是介于块设备和字符设备之间的一种特殊设备。
块设备接口仅支持面向块的I/O操作,所有I/O操作都通过在内核地址空间中的I/O 缓冲区进行,它可以支持随机存取的功能。文件系统通常都建立在块设备上。
• YAFFS (Yet Another Flash File System)
• ROMFS
• RAMFS • JFFS2(Journaling Flash File System)
• 设备控制
– 几乎每一个系统操作都会映射到物理设备上 – 除去CPU,内存以及其他几个很有限的对象之外,几乎所有
的设备控制操作都由与被控制设备相关的代码(设备驱动程 序)来完成
查询方式白白浪费了大量的处理器时间,而中断方式才是多任务操作系统中最有效利 用处理器的方式。当CPU进行主程序操作时,外设的数据已存入端口的数据输入寄存器, 或端口的数据输出寄存器已空,此时由外设通过接口电路向CPU发出中断请求信号。 CPU在满足一定条件下,暂停执行当前正在执行的主程序,转入执行相应能够进行输入/ 输出操作的子程序,待输入/输出操作执行完毕之后,CPU再返回并继续执行原来被中断 的主程序。这样,CPU就避免了把大量时间耗费在等待、查询外设状态的操作上,使其工 作效率得以大大提高。中断方式的原理示意图如图6.1所示。
字符设备接口支持面向字符的I/O操作,由于它们不经过系统的快速缓存,所以它 们负责管理自己的缓冲区结构。字符设备接口只支持顺序存取的功能,一般不能进行 任意长度的I/O请求,而是限制I/O请求的长度必须是设备要求的基本块长的倍数。
Linux设备驱动程序课件(PPT 62页).ppt
一些重要的数据结构
索引节点inode结构
Inode结构包含大量描述文件信息的成员变量。 但是对于描述设备文件的inode,跟设备驱动有关
的成员只有两个。 Dev_t i_rdev; 包含真正的设备编号。 Struct cdev *i_cdev; 指向cdev结构体的指针。
cdev是表示字符设备的内核数据结构。 从inode中获得主设备号和次设备号的宏:
一些重要的数据结构
file_operations重要的成员
驱动内核模块是不需要实现每个函数的。相对应的 file_operations的项就为 NULL。
Gcc的语法扩展,使得可以定义该结构体: struct file_operations fops = {
read: device_read, write: device_write, open: device_open, release: device_release };
设备文件: 任何设备都被当作路径/dev 的设备文件处理,并通 过这些设备文件提供访问硬件的方法。 每个设备文件除了设备名外,还有类型、主设备号、 次设备号这三个属性。 设备文件是通过mknod系统调用创建的。其原型为: mknod(const char * filename, int mode, dev_t dev) mknod /dev/led0 c 253 0
Linux设备驱动
广州嵌入式软件公共技术支持中心
2007年07月
设备驱动概述
操作系统是通过各种驱动程序来驾驭硬件设备,它为 用户屏蔽了各种各样的设备,硬件设备的抽象。
设备驱动程序:处理和管理硬件控制器的软件。 设备驱动程序是操作系统内核和机器硬件之间的接口。
第7章 嵌入式Linux设备驱动程序开发(inode解释说明)PPT课件
//文件最后修改的时间
time_t
i_ctime;
//结点最后修改的时间
unsigned int
i_blkbits; //位数
unsigned long i_blksize; //块大小
unsigned long i_blocks;
//文件所占用的块数
unsigned long i_version; //版本号
struct address_space i_data;
//数据
struct dquot *i_dquot[MAXQUOTAS];
//索引结点的磁盘限额
struct list_head
i_devices;
//设备文件形成的链表
struct pipe_inode_info
*i_pipe; //指向管道文件
struct semaphore
i_sem;
//用于同步操作的信号量结构
第7章 嵌入式Linux设备驱动程序开发
struct semaphore
i_zombie;
//索引结点的信号量
struct inode_operations
*i_op; //索引结点操作
struct *i_fop; //指向文件操作的指针
loff_t *); ssize_t (*writev) (struct file *, const struct iovec *, unsigned long,
loff_t *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t,
struct { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned
嵌入式Linux设备驱动程序开发ppt课件
.
10.1 嵌入式Linux驱动程序开发基础
② int schedule_work(struct work_struct *work) ③int schedule_delayed_work(struct work_struct *work, unsigned long delay) ④void flush_scheduled_work(void)
Linux将设备按照功能特性划分为三种类型:字符设 备,块设备和网络设备。 10.1.2 最简单的内核模块 1.helloworld模块源代码 2.模块的编译 3.模块的加载和卸载
.
10.1 嵌入式Linux驱动程序开发基础
10.2 嵌入式Linux设备驱动重要技术 10.2.1 内存与I/O端口 (1)内核空间和用户空间 (2)内核中内存分配 内核中获取内存的几种方式如下。 ①通过伙伴算法分配大片物理内存 ②通过slab缓冲区分配小片物理内存 ③非连续内存区分配 ④高端内存映射 ⑤固定线性地址映射
.
10.1 嵌入式Linux驱动程序开发基础
1.原子操作 原子操作主要用于实现资源计数,很多引用计数(refcnt)就是 通过原子操作实现的。
原子类型定义如下: typedef struct { volatile int counter; } atomic_t; 原子操作通常用于实现资源的引用计数 2.信号量
信号量在创建时需要设置一个初始值. 3.读写信号量
读写信号量有两种实现:
一种是通用的,不依赖于硬件架构 一种是架构相关的
.
10.1 嵌入式Linux驱动程序开发基础
读写信号量的相关API有: DECLARE_RWSEM(name) 该宏声明一个读写信号量name并对其进行初始化。 void init_rwsem(struct rw_semaphore *sem); 该函数对读写信号量sem进行初始化。 void down_read(struct rw_semaphore *sem);
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
设备分类
块设备:一般块设备都有缓存支持,并且支持随机 存取
创建的块设备
硬盘 软盘 ramdisk
ChavezWang@
嵌入式系统研究室
5
设备驱动的基本原理-4
设备分类
网络设备:从BSD UNIX网络组件移植而来。网络 设备没有对应地映射到文件系统的设备节点。在 Linux中,网络设备的访问采用Socket机制实现
注册Linux设备号的方法
为避免不同的驱动程序具有相同的设备号,需要 提供一种分配设备号的机制
1. 每个驱动程序分配一个主设备号:不可行,Linux最多 支持255个主设备
2. 根据/proc/devices中的对应关系,用脚本动态的创建设 备文件:太麻烦,程序员不愿意
3. 设备文件系统自动管理
ChavezWang@
嵌入式系统研究室
6
设备驱动的基本原理-5
设备号:Linux采用主设备号和次设备号来标志 一个具体设备。
主设备号用来标志设备类型 次设备号用来区分不同的具体设备
系统创建一个设备驱动程序时,设备驱动需要 使用一个主设备号向内核注册此驱动。创建一 个设备节点的方法:
mknod 设备名 设备类型 主设备号 次设备号 例:mknod ttyS0 c 64 4
ChavezWang@
嵌入式系统研究室
7
设备驱动的基本原理-6-内核模块
内核模块的概念:内核模块是一些可以让操作 系统内核在需要时载入和执行的代码,不Байду номын сангаас要 时可以从操作系统中卸载
内核模块是Linux内核运行时动态扩展的一种 技术,可以在Linux内核运行期间向内核动态 添加代码,扩展内核的功能
加入新驱动到内核源码树时,需要修改相应目录的 kconfig,将新驱动加入内核的配置菜单,同时需要 修改makefile文件
ChavezWang@
嵌入式系统研究室
11
设备驱动的基本原理-10-内核模块
Scrip/makefile
Makefile
menuconfig
.config
ChavezWang@
嵌入式系统研究室
8
设备驱动的基本原理-7-内核模块
内核模块与应用程序加载的不同:
内核模块的加载只是向内核预先注册自己以便服务于将来 的某个请求,只是加载了某项功能,而不需要马上执行
应用程序加载后就开始执行 内核模块不能使用外部函数库,只能使用内核导出的函数 应用程序可以使用外部函数库 内核模块只能运行在内核空间,并且不生成新的进程 应用程序运行在用户空间,一般一个应用程序生成一个新
设备驱动
HARDWARE
ChavezWang@
嵌入式系统研究室
3
设备文件与设备文件系统
Linux中,字符设备和块设备都是通过文件节 点进行访问。
每个设备对应一个文件名,操作时对应各自的 驱动程序。
设备文件与设备文件系统
Linux系统靠主次设备号来联系驱动程序和设 备文件节点,依靠主设备号标志不同的驱动 程序
Linux驱动程序设计
主要内容
设备驱动的基本原理 设备驱动的编写方法 2.6内核设备模型框架 设备驱动中的中断处理方法 串口读写程序实例
ChavezWang@
嵌入式系统研究室
2
设备驱动的基本原理-1
USER APP
用户空间
VFS
内核空间
DEVICE op func DEV_REGISTER
注册Linux设备号的方法
系统启动时,会把设备驱动程序挂载在/dev/目 录下,Linux设备文件的创建和删除、目录层 次都都由各个设备驱动程序管理
/dev/下面每个文件都动态对应了一个系统上存 在的设备驱动程序。
新添加(或者删除)一个设备,比如u盘,系 统就会自动在/dev目录中创建(或者删除)对 应的设备节点。
嵌入式系统研究室
10
设备驱动的基本原理-9-内核模块
2.6系列内核模块的编译与加载
内核源码树的每个子目录都有一个kconfig文件,为 makefile提供配置数据库,分别描述了所属目录源 文件相关的内核配置菜单项
内核配置时,从kconfig中读出配置菜单,配置后生 成.config文件
编译内核时,makefile读入对应的.config文件生成 内核映像
的进程
ChavezWang@
嵌入式系统研究室
9
设备驱动的基本原理-8-内核模块
内核模块的框架
#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) { printk(KERN_ALERT "Hello, world\n");
return 0; } static void hello_exit(void){
printk(KERN_ALERT "Goodbye, world\n");} module_init(hello_init); module_exit(hello_exit);
ChavezWang@
设备驱动的基本原理-2
设备分类
字符设备:存取时没有缓存、只能顺序读/写的设备。 可通过设备文件节点被访问
与普通文件的区别:普通文件的访问可以前后移动访问指 针,而大多数字符设备不支持该操作。
典型的字符设备
鼠标 键盘 串口
ChavezWang@
嵌入式系统研究室
4
设备驱动的基本原理-3
注册Linux设备号的方法
在设备文件系统中,由于分的比较细致,一些 驱动程序的对应目标跟以前比一样,如:
Linux2.4之前:/dev/fb0 /dev/ttyS0 Linux2.6之后:/dev/fb/0 /dev/tts/0
可以用符号链接进行更改,以便与之前的相匹 配:
ln-s /dev/fb/0 /dev/fb0 ls-s /dev/tts/0 /dev/ttyS0
Kconfig 输出
arch/arm/makefile makefile
makefile
块设备:一般块设备都有缓存支持,并且支持随机 存取
创建的块设备
硬盘 软盘 ramdisk
ChavezWang@
嵌入式系统研究室
5
设备驱动的基本原理-4
设备分类
网络设备:从BSD UNIX网络组件移植而来。网络 设备没有对应地映射到文件系统的设备节点。在 Linux中,网络设备的访问采用Socket机制实现
注册Linux设备号的方法
为避免不同的驱动程序具有相同的设备号,需要 提供一种分配设备号的机制
1. 每个驱动程序分配一个主设备号:不可行,Linux最多 支持255个主设备
2. 根据/proc/devices中的对应关系,用脚本动态的创建设 备文件:太麻烦,程序员不愿意
3. 设备文件系统自动管理
ChavezWang@
嵌入式系统研究室
6
设备驱动的基本原理-5
设备号:Linux采用主设备号和次设备号来标志 一个具体设备。
主设备号用来标志设备类型 次设备号用来区分不同的具体设备
系统创建一个设备驱动程序时,设备驱动需要 使用一个主设备号向内核注册此驱动。创建一 个设备节点的方法:
mknod 设备名 设备类型 主设备号 次设备号 例:mknod ttyS0 c 64 4
ChavezWang@
嵌入式系统研究室
7
设备驱动的基本原理-6-内核模块
内核模块的概念:内核模块是一些可以让操作 系统内核在需要时载入和执行的代码,不Байду номын сангаас要 时可以从操作系统中卸载
内核模块是Linux内核运行时动态扩展的一种 技术,可以在Linux内核运行期间向内核动态 添加代码,扩展内核的功能
加入新驱动到内核源码树时,需要修改相应目录的 kconfig,将新驱动加入内核的配置菜单,同时需要 修改makefile文件
ChavezWang@
嵌入式系统研究室
11
设备驱动的基本原理-10-内核模块
Scrip/makefile
Makefile
menuconfig
.config
ChavezWang@
嵌入式系统研究室
8
设备驱动的基本原理-7-内核模块
内核模块与应用程序加载的不同:
内核模块的加载只是向内核预先注册自己以便服务于将来 的某个请求,只是加载了某项功能,而不需要马上执行
应用程序加载后就开始执行 内核模块不能使用外部函数库,只能使用内核导出的函数 应用程序可以使用外部函数库 内核模块只能运行在内核空间,并且不生成新的进程 应用程序运行在用户空间,一般一个应用程序生成一个新
设备驱动
HARDWARE
ChavezWang@
嵌入式系统研究室
3
设备文件与设备文件系统
Linux中,字符设备和块设备都是通过文件节 点进行访问。
每个设备对应一个文件名,操作时对应各自的 驱动程序。
设备文件与设备文件系统
Linux系统靠主次设备号来联系驱动程序和设 备文件节点,依靠主设备号标志不同的驱动 程序
Linux驱动程序设计
主要内容
设备驱动的基本原理 设备驱动的编写方法 2.6内核设备模型框架 设备驱动中的中断处理方法 串口读写程序实例
ChavezWang@
嵌入式系统研究室
2
设备驱动的基本原理-1
USER APP
用户空间
VFS
内核空间
DEVICE op func DEV_REGISTER
注册Linux设备号的方法
系统启动时,会把设备驱动程序挂载在/dev/目 录下,Linux设备文件的创建和删除、目录层 次都都由各个设备驱动程序管理
/dev/下面每个文件都动态对应了一个系统上存 在的设备驱动程序。
新添加(或者删除)一个设备,比如u盘,系 统就会自动在/dev目录中创建(或者删除)对 应的设备节点。
嵌入式系统研究室
10
设备驱动的基本原理-9-内核模块
2.6系列内核模块的编译与加载
内核源码树的每个子目录都有一个kconfig文件,为 makefile提供配置数据库,分别描述了所属目录源 文件相关的内核配置菜单项
内核配置时,从kconfig中读出配置菜单,配置后生 成.config文件
编译内核时,makefile读入对应的.config文件生成 内核映像
的进程
ChavezWang@
嵌入式系统研究室
9
设备驱动的基本原理-8-内核模块
内核模块的框架
#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) { printk(KERN_ALERT "Hello, world\n");
return 0; } static void hello_exit(void){
printk(KERN_ALERT "Goodbye, world\n");} module_init(hello_init); module_exit(hello_exit);
ChavezWang@
设备驱动的基本原理-2
设备分类
字符设备:存取时没有缓存、只能顺序读/写的设备。 可通过设备文件节点被访问
与普通文件的区别:普通文件的访问可以前后移动访问指 针,而大多数字符设备不支持该操作。
典型的字符设备
鼠标 键盘 串口
ChavezWang@
嵌入式系统研究室
4
设备驱动的基本原理-3
注册Linux设备号的方法
在设备文件系统中,由于分的比较细致,一些 驱动程序的对应目标跟以前比一样,如:
Linux2.4之前:/dev/fb0 /dev/ttyS0 Linux2.6之后:/dev/fb/0 /dev/tts/0
可以用符号链接进行更改,以便与之前的相匹 配:
ln-s /dev/fb/0 /dev/fb0 ls-s /dev/tts/0 /dev/ttyS0
Kconfig 输出
arch/arm/makefile makefile
makefile