见char_load和char_unload脚本。
(3)字符设备的基本数据结构
和字符设备驱动关系最紧密的3个基本的数据结构是:file, file_oepeations和inode
a.file_operations数据结构
结构中包含了若干函数指针。这些函数就是实际和硬件打交道的函数。
用户空间调用的open,write等函数最终会调用这里面的指针所指向的函数。每个打开的文件和一组函数关联。
见<linux/fs.h>和驱动书的p54
2.6内核结构的初始化:
| struct file_operations my_fops = { .owner = THIS_MODULE, .llseek = my_llseek, .read = my_read, .write = my_write, .ioctl = my_ioctl, .open = my_open, .release = my_release, } |
2.4内核结构的初始化:
| struct file_operations my_fops = { owner: THIS_MODULE, llseek: my_llseek, ... } |
b.file结构<linux/fs.h>
file是一个内核结构体,实际上和用户open文件后返回的文件描述符fd对应。
file结构代表一个打开的文件,系统中每个打开的文件在内核空间都有一个对应的file结构。
它由内核在open时创建,并传递给在该文件上进行操作的所有函数,直到最后的close函数,在文件的所有实例都被关闭后,内核会释放这个结构。
用户空间进程fork一个新进程后,新老进程会共享打开的文件描述符fd,这个操作不会在内核空间创建新的file结构,只会增加已创建file结构的计数。
见<linux/fs.h>
mode_t f_mode; 通过FMODE_READ和FMODE_WRITE标示文件是否可读或可写。
loff_t f_pos; 当前的读写位置,loff_t为64位
unsigned int f_flags; 文件标志,如O_RDONLY, O_NONBLOCK, O_SYNC。标志都定义在<linux/fcntl.h>
struct file_operations *f_op; 与文件相关的操作。内核在执行open时对这个指针赋值。可以在驱动的open方法中根据次设备号赋予不同的f_op
void *private; 通常将表示硬件设备的结构体赋给private.
struct dentry *f_dentry; 文件对应的目录项(dentry)结构。可通过filp->f_dentry->d_inode访问索引节点。
file中其他的内容和驱动关系不大。
c.inode结构
内核用inode结构表示一个实际的文件,可以是一个普通的文件,也可以是一个设备文件。
每个文件只有一个inode结构,而和文件描述符对应的file结构可以有多个(多次进行open调用)。这些file都指向同一个inode。
inode定义在<linux/fs.h>
dev_t i_rdev; 对于表示设备文件的inode结构,i_rdev里包含了真正的设备编号
struct cdev *i_cdev cdev是表示字符设备的内核的内部结构。当inode表示一个字符设备时,i_cdev指向内核中的struct cdev.
其他结构和设备驱动关系不大。
用如下宏从inode获取设备号:








