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 /* Needed by all modules */

#include /* Needed for KERN_ALERT */

#include /* Needed for the module-macros */

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!

卸载模块