理论基础:
1.几个重要的结构体:
(1)cedv结构体
struct cdev
{
struct kobject kobj; //内嵌的kobject结构,用于内核设备驱动模型的管理(驱动开发一般不适用该成员)
struct module *owner; //指向包含该结构的模块的指针,用于引用计数
const struct file_operations *ops; //指向字符设备操作函数集的指针
struct list_head list; //该结构将使用该驱动的字符设备连接成一个链表
dev_t dev; //存储该字符设备的起始设备号,一个设备可能有多个设备号
unsigned int count; //使用该字符设备驱动的设备数量,当使用rmmod卸载模块时,如果count成员不为0则不允许卸载
}
(2)file_operations结构体:
file_operations
{
struct module *owner; //owner成员根本不是一个函数,其功能与struct cdev中一样
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
...
};
(3)inode结构体:
inode
{
dev_t i_rdev; //表示设备文件对应的设备号
struct list_head i_devices; //连接到对应的cdev结构,从而对应到自己的驱动程序
struct cdev *i_cdev; //指向cdev设备
...
};
2.三种结构体之间的关系:
一般,我们会将特点设备(就是具体的某个设备)的特定数据(具体的数据)放到dev结构体之后,组成一个新的结构体“自定义设备”。
inode一般作为file_operations结构体中函数的参数传递过来。另外,除了可以从cdev的dev_t得到主设备好和次设备号外,还可以用imajor()和iminor()函数从inode的i_rdev中得到。