之前我们说过,Linux设备主要分为三类:字符设备、块设备和网路插口。
字符设备相对于另外两个设备愈发容易理解,同时,这类设备也适宜大多数简单的硬件设备,为此,接出来我们学习一下字符设备驱动。
字符驱动的学习分为两节:先介绍一下字符驱动驱动中的一些概念,这种概念有些在块设备中也是相同的;之后基于的显存创建一个字符设备实例。
本节主要介绍一下驱动中的一些概念,主要学会以下内容:
设备号及其相关操作
字符设备一般坐落/dev目录下,通过设备的名称进行访问,这种名称称为设备文件或节点。在/dev目录下,使用ls-l来查看系统中的设备情况,部份结果如下:
ls-l查看设备情况
在每行的最上面的有一个字符(c、d、l、b等)红旗linux6.0,其中,c开头的设备表示的就是字符设备。(类似的,b开头的设备表示块设备、d表示是一个目录、l表示是一个联接)
截图中的字符设备为btrfs-control,具体信息如下:
crw------- 1 root root 10, 234 7月 25 10:45 btrfs-control
其中的:10,234表示的就是设备的设备号linux设备驱动开发详解 源码,10为主设备号(misc字符设备),234为次设备号。
主设备号用于表示设备对应的驱动程序。Linux内核允许多个驱动程序共享主设备号linux设备驱动开发详解 源码,但许多设备依然根据一个设备号对应一个驱动程序的原则组织;次设备号由内核使用linux系统,用于正确确定设备文件所指的设备,借助次设备号可以获取一个指向内核设备的直接表针,也可以将次设备号当作设备本地字段的索引。
在头文件中提供了一个dev_t类型来保存设备号——在2.6.0内核中,dev_t类型是32位的,其中的12位拿来表示主设备号,剩余20位拿来表示次设备号。但我们不要默认永远都是这样实现的,而应当借助中定义的两个宏来获取dev_t所表示的设备号:
MAJOR(dev_t dev); //返回主设备号
MINOR(dev_t dev); //返回次设备号
同样,当晓得主设备号和次设备号时,也不要自己自动去拼接生成dev_t变量,而应使用以下宏实现:
MKDEV(int major, int minor); //返回dev_t变量
在驱动程序中,对于设备号的相关操作主要是分配和释放,操作函数都在中进行了申明,主要有以下几个函数:
int register_chrdev_region(dev_t first, unsigned int count, char *name);
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
void unregister_chrdev_region(dev_t first, unsigned int count);
对其中的参数进行说明:
register_chrdev_region看名子就晓得是注册设备号,这个函数适用于注册所需设备编号已知的情况下;在大多数情况下,我们是不晓得设备编号的,可以使用alloc_chrdev_region来分配设备编号;unregister_chrdev_region看名子也晓得,是释放注册的设备编号,通常在退出函数中调用。
对于register_chrdev_region和alloc_chrdev_region,强烈建议使用alloc_chrdev_region来分配设备编号,这样可以促使驱动程序适应性更强。
分配设备编号是驱动代码须要完成的第一件事,后续还须要将内部函数和设备编号联接上去。
文件操作相关的数据结构
文件操作相关的数据结构主要是结构体structfile_operations,其定义在中。
该结构体包含了一组函数表针,用于将内部函数和里面的设备编号联接上去。
该结构体的具体内容请自行查看源码,下边对平时用得比较多的几个函数进行说明:
struct file_operations {
struct module *owner;
......
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
......
__poll_t (*poll) (struct file *, struct poll_table_struct *);
......
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
......
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
......
} ;
目前只要晓得有这个结构体即可,可以在后续驱动中须要使用的时侯再去深入了解。
文件相关的数据结构
文件相关的数据结构主要是structfile结构体,其定义在中。
该结构体表示一个打开的文件,它由内核在open时创建,为此系统中每位打开的文件、设备都有一个对应的file结构体。在文件的所有实例都被关掉后,内核就会释放这个结构体。
具体内容查看源码,下边对比较重要的属性进行说明:
struct file {
......
const struct file_operations *f_op;
......
unsigned int f_flags;
fmode_t f_mode;
......
loff_t f_pos;
......
void *private_data;
......
}
同样,这个结构体目前只须要了解即可,后续假如有须要再深入了解。
节点相关的数据结构
里面介绍了structfile_operations结构体表示文件操作相关的结构体,structfile结构体表示打开的文件。下边介绍的structinode结构体表示的是文件(节点)。该结构体同样坐落中。
structinode中包含了大量的有关文件的信息,其中对于驱动程序编撰十分重要的主要有以下几个:
struct inode {
......
dev_t i_rdev;
......
union {
......
struct cdev *i_cdev;
......
};
......
};
以上是本节的主要内容,下一节将会编撰一个字符设备实例。
本文原创地址://q13zd.cn/lsbhjqxgczzf.html编辑:刘遄,审核员:暂无