2024年6月6日发(作者:)
嵌入式Linux驱动
1 简介
设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程
序屏蔽了硬件的细节,这样使硬件对应用程序来说是透明的,在应用程序看来,
硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行
操作。设备驱动程序是嵌入式Linux内核的一部分,它完成以下的功能:
· 对硬件设备初始化和释放
· 把数据从内核传送到硬件,或从硬件读取数据
· 读取应用程序传送给设备文件的数据和回送应用程序请求的数据
·检测和处理设备出现的错误和异常
Linux系统的设备分为字符设备,块设备和网络设备。用户进程通过设备文件
实现与硬件的交流。每个设备文件都有其文件属性,表示是字符设备还是块设备。
另外每个文件都有两个设备号:第一个是主设备号,标识驱动程序;第二个是从
设备号,标识使用同一个设备驱动程序的不同硬件设备。
设备驱动程序可以分为3个主要组成部分:
(1) 自动配置和初始化
用于负责检测所要驱动的硬件设备是否存在和是否能正常工作。如果该设备
正常,则对这个设备及其相关设备驱动程序需要的软件状态进行初始化,如设置
寄存器的值,初始化驱动程序用到的数据结构。这部分驱动程序仅在初始化的时
候被调用一次。
(2)服务于I/O请求的子程序
调用服务于I/O请求的子程序是由于系统调用的结果,如read,write调用。
这部分程序在执行的时候,系统仍认为是和进行调用的进程属于同一个进程,只
是由用户态变成了核心态,它们的运行环境和进行此系统调用的用户程序一样,
因此可以在其中调用sleep()等与进程运行环境有关得函数。
(3)中断服务子程序
在UNIX系统中,并不是直接从中断向量表中调用设备驱动程序的中断服务子
程序,而是由UNIX系统来接收硬件中断,再由系统调用中断服务子程序。中断
可以发生在任何一个进程运行的时候,因此在中断服务程序被调用的时候,不能
依赖于任何进程的状态,也就不能调用任何与进程运行环境有关的函数。因为设
备驱动程序一般支持同种类型的若干设备,所以一般在系统调用中断服务子程序
的时候,都带有一个或多个参数,以唯一标识请求服务的设备。
2 一个简单的Linux2.6内核驱动模块(hello world)
/* hello.c */
#include
#include
#include
static int __init hello_init(void) // Module entry function specified by
module_init()
{
printk(KERN_ALERT "Hello,world!n");
return 0;
}
static void __exit hello_exit(void) //Module exit function specified by
module_exit()
{
printk(KERN_ALERT "Goodbye,cruel world!n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("Dual BSD/GPL"); //should always exist or you’ll get a
warning
MODULE_AUTHOR("BENSON"); //optional
MODULE_DESCRIPTION("STUDY_MODULE"); //optional
/* Makefile */
# Makefile 2.6
obj-m = hello.o
KDIR:=/lib/modules/$(shell uname -r)/build
#PWD=$(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
************************************************
obj-m := hello.o表示编译后生成hello.o模块。
$(KDIR) 指定了内核源码的路径,“M=”表示这是个外部模块,M=$(PWD) 指定
了该模块文件所在的路径。
注: makefile预定义了$(PWD)变量,此处可以不必重复定义。
执行#make编译成功后
加载模块
#insmod 字串7
#lsmod 输出内核已加载模块信息,可以查看到刚刚加载成功的hello模块
„„
Module Size Used by
hello 5632 0
可以在日志里查看加载模块时的信息
#vi /var/log/messages
„„
Sep 27 13:25:21 localhost kernel: Hello,world!
卸载模块


发布评论