第1章
Linux是一种性能优良、源码公开、多用户、多任务操作系统,目前主要运用在大型服务器领域、网络处理应用和嵌入式系统。为了加强在嵌入式系统领域的优势,Linux 2.6已经在内核中加入了提高中断性能和调度响应时间的改进,加入了对多种微控制器的支持。
1.1 驱动程序的概念
设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节。在应用程序看来,硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作。
编写设驱动必须掌握操作系统的工作原理,并对硬件设备的运行机制清楚。开发设备驱动程序必须注意代码的安全性。因为驱动程序的错误往往导致整个操作系统崩溃。另外,同一个设备驱动可能被不同的进程调用,所以开发设备驱动程序必须考虑并发问题的处理。
1.2 Linux驱动程序模型
在Linux操作系统中,设备驱动程序对各种不同设备提供了一致的访问接口,把设备映射为一个特殊的设备,用户程序可以像对其他文件一样对此设备文件进行操作。Linux支持三类硬件设备:字符设备 、块设备及网络设备。
网络设备在做数据包发送和接收时,直接通过接口访问,不需要进行文件的操作;而对字符设备和块设备的访问都需要通过文件操作界面。
Linux系统为每个设备分配了一个主设备号与次设备号,主设备号唯一标识了设备类型,次设备号标识具体设备的实例。
在驱动程序中,可以用下列宏获得驱动的设备号:
MAJJOR(dev_t dev);
MINOR(ddev_t dev);
Linux 2.6内核开发了全新的设备模型,它采用sysfs文件系统,类似于proc文件系统的特殊文件系统,用于将系统中的设备组织成层次结构,并向用户模式提供详细的内核数据结构信息。
Linux 2.6引入新的设备管理机制Kobject,通过这个数据结构使所有设备在底层都具有统一的接口,kobject提供基本的对象管理,是构成Linux2.6内核设备模型的核心机构,它与sysfs文件系统紧密关联,每个在内核中注册的kobject对象都对应于sysfs文件系统中的一个目录。kobject通常通过kset组织成层次化的结构,kset是具有相同类型的kobject的集合。
struct kobject{
char * k_name;
char * name[KOBJ_NAME_LEN];
atomic_t refcount;
struct list_head entry;
struct kobject * parent;
struct kset * kset;
struct kobj_type * ktype;
struct dentry * dentry
};
struct kset{
struct subsystem * sussys;
sturct kobj_type * ktype;
struct list_head list;
struct kobject koj;
struct kset_hotplug_ops * hotplug_ops;;
};
在这些内核对象机制的基础上,Linux的设备模型(include/linux/device.h)包括设备结构devices、驱动结构drivers、总线结构buses、设备类结构classes几个关键组件。Linux中的任一设备在设备模型中都由一个device对象描述,其对应的数据结构struct device定义为:
struct device{
struct list_head node; //在同类设备列表中的节点
struct list_head bus_list; //在总线列表中节点
struct list_head driver_list;
struct list_head children;
struct device * parent; //父设备
struct kobject kobj;
char bus_id[BUS_ID_SIZE]; //父总线上的ID
struct bus_type * bus; //设备挂接的总线类型
struct device_driver * driver //分配本设备的驱动
void * driver_data;//私有数据
void * platform_data; //平台特定数据(包括与设备相关的ACPI,BIOS数据)
struct dev_pm_info power;
u32 power_state; //电源状态,在ACPI中包括D0~D3,D0表示全功能,D3表示停止
unsiged char * saved_state; //设备状态
u32 detach_state; //设备删除时进入的状态
u64 *dma_mask; //DMA掩码
u64 coherent_dma_mask; //类似DMA掩码,用于alloc_coherennt_mappings
struct list_head dma_pools; //DMA池
void (*release) (struct device * dev);
};
//注册与注销函数
int device_register(struct device * dev);
void device_unregister(struct device * dev);
系统中的每个驱动程序由一个device_driver对象描述,对应的数据结构定义为:
struct device_driver{
char * name; //设备驱动程序的名称
struct bus_type * bus; //该驱动所管理的设备挂接的总线类型
struct semaphore unload_sem;
struct kobject kobj; //内嵌kobject对象
struct list_head devices; //该驱动所管理的设备链表头
int (*probe) (struct device * dev); //指向设备探测函数,探测设备是否可以被该驱动程序管理
int (*remove) (struct device * dev); //用于删除设备的函数
void (*shutdown) (struct device * dev); //停止设备的函数
int (*suspennd) (struct device * dev, u32 state, u32 level); //挂起设备的函数
int (*resume) (struct device * dev, u32 level); //恢复设备的函数
};
//注册与注销函数
int driver_register(struct device_driver * drv);
void driver_unregister(struct device_driver * drv);
系统中总线由struct bus_type描述,定义为:
struct bus_type{
char * name; //总线类型的名称
struct subsystem subsys; //与该总线相关的subsystem
struct kset drivers; //所有与该总线相关的驱动程序集合
struct kset devices; //所有挂接在该总线上的设备集合
struct bus_attribbute * bus_attrs; //总线属性
struct device_attribute * dev_attrs; //设备属性
struct drvier_attribute * drv_attrs; //驱动程序属性
int (match) (struct device * dev, struct device_driver * drv);
int (hotplug) (struct device * dev, char **ennvp, int num_envp, char *buffer, int buffer_size);
int (suspend) (struct device * dev, u32 state);
int (resume) (struct device * dev);
};