现在的位置: 首页 > 综合 > 正文

字符设备驱动程序设计

2017年08月25日 ⁄ 综合 ⁄ 共 2739字 ⁄ 字号 评论关闭

设备号---主设备号,次设备号

字符设备通过字符设备文件来存取。字符设备文件由使用ls -l的输出的第一列的c标识。其中的两个数字,分别为主设备号和次设备号。

设备号作用-----

主设备号----字符设备文件通过主设备号和字符设备驱动对应

次设备号--被驱动程序用来辨别操作的是哪个设备。

总结---主设备号用来反映设备类型,次设备号用来区分同类型的设备

内核中描述设备号---dev_t

其实质为unsigned int 32位整数,其中高12位为主设备号,低20位为次设备号。

主设备号---MAJOR(dev_t dev)

次设备号--MINOR(dev_t dev)

分配主设备号---

---静态申请

方法:

1--根据Documentation/devices.txt确定一个没有使用的主设备号

2--使用register_chrdev_region函数注册设备号

缺点--随机选定的主设备号可能会导致设备号冲突,而使驱动程序无法注册。

int register_chrdev_region(

dev_t from,申请使用的设备号

unsigned count,申请使用的设备号数目

const char *name设备名(体现在/proc/devices)

)

申请使用从from开始的count个设备号(主设备号不变,次设备号增加)



---动态分配

方法:

使用alloc_chrdev_region分配设备号

缺点--无法在安装驱动前创建设备文件(因为安装前还没有分配到主设备号)

解决办法---安装驱动后,从/proc/devices中查询设备号。

int alloc_chrdev_region(

dev_t *dev,分配到的设备号,获取值

unsigned baseminor,起始次设备号

unsigned count,需要分配的设备号数目

const char *name设备名(体现在/proc/devices)

)

功能--请求内核动态分配count个设备号,且此设备号从baseminor开始。

注销设备号----不再使用它们时释放这些设备号

void unregister_chrdev_region(dev_t from,unsigned conunt)

功能:释放从from开始的count个设备号。

创建设备文件---

1--使用mknod

mknod filename type major minor

filename---设备文件名

type---设备文件类型

major---主设备号

minor---次设备号

mknod serial0 c 100 0

2--自动创建

重要结构----字符设备驱动程序设计

struct file---代表一个打开的文件。系统中每个打开的文件在内核空间都有一个关联的struct file。 它由内核在打开文件时创建,在文件关闭后释放。

重要成员----

loff_t f_pos---文件读写位置

struct file_operations *f_op--

一个函数指针的集合,定义在设备上进行的操作。结构中的成员指向驱动中的函数,这些函数实现一个特别的操作,对于不支持的操作保留为NULL。

struct file_operations mem_fops=

{

.owner=THIS_MODULE,

.llseek=mem_seek,

.read=mem_read,

.write=mem_write,

.ioctl=mem_ioctl,

.open=mem_open,

.release=mem_release,

};

struct inode----用来记录文件的物理上的信息。因此,它和代表打开文件的file结构是不同的。一个文件可以对应多个file结构,但只有一个inode结构。

重要成员---

dev_t i_rdev---设备号

设备注册----

在linux2.6内核中,字符设备使用struct cdev来描述

字符设备的注册可分为如下3步----

1---分配cdev

struct cdev *cdev_alloc(void)

返回一个cdev结构

2---初始化cdev

void cdev_init(

struct cdev *cdev,待初始化的cdev结构

const struct file_operation *fops设备对应的操作函数集

)

3--添加cdev

int cdev_add(

struct cdev *p,待添加到内核的字符设备结构。

dev_t dev,设备号

unsigned conunt添加的设备个数

)

设备操作实现---设备支持的操作

int (*open)(struct inode *,struct file *)

在设备文件上的第一个操作,并要求驱动程序一定要实现这个方法。如果该项为NULL,设备的打开操作永远成功。

是驱动程序用来为以后的操作完成初始化准备工作的。一般完成以下工作,

初始化设备,标明次设备号。

void (*release) (struct inode *,struct file *)

当设备文件被关闭时调用这个操作。与open相仿,release也可以没有。

关闭设备

ssize_t (*read) (struct fiel *,char __user *,size_t,loff_t *)

从设备中读取数据,读取数据到用户空间

ssize_t (*write) (struct fiel *,const char __user *,size_t,loff_t *)

向设备发送数据,将数据传递给驱动程序。

对于以上两个方法,filp是文件指针,count是请求传输的数据量。buff参数指向数据缓存。最后,offp指出当前的访问位置。

buff参数是用户空间指针。因此它不能被内核代码直接使用,因为用户空间的指针在内核空间时可能根本是无效的----没有那个地址的映射。

内核提供专门的函数用于访问用户空间的指针

int copy_from_user(void *to,const void __user *from,int n)

int copy_to_user(void __user *to,const void *from,int n)


unsigned int (*poll) (struct file *,struct poll_table_struct *)


对应select系统调用

int (*ioctl) (struct inode *,struct file *,unsigned int ,unsigned long)

控制设备

int (*mmap) (struct file *,struct vm_area_struct *)

将设备映射到进程虚拟地址空间中

off_t (*llseek) (struct file *,loff_t,int)

修改文件的当前读写位置,并将新位置作为返回值

设备注销----

int cdev_del(struct cdev *p)

p---要注销的字符设备结构。





【上篇】
【下篇】

抱歉!评论已关闭.