构造struct file_operations结构体
file_operations定义
struct file_operations
{
struct module *owner;
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 *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
int (*iterate) (struct file *, struct dir_context *);
unsigned int (*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 *);
void (*mremap)(struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, loff_t, loff_t, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long,unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t,unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t,unsigned int);
int (*setlease)(struct file *, long, struct file_lock **, void **);
long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len);
void (*show_fdinfo)(struct seq_file *m, struct file *f);
};
对于一个设备驱动并不需要完成所有函数的映射,可以有选择地进行使用,下面对最常用的几项进行说明:
这个域是用来设置指向“拥有”该结构的模块指针,内核使用该指针维护模块的使用计数。
struct module *owner;
read域用来从设备中读数据,需要提供字符串指针。从设备中读取数据时,
成功返回所读取的字节数,read等于NULL时,将导致调用失败,并返回-EINVAL。
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
write域用来向字符设备写数据,需要提供所写指针内容。当向设备写入数据时,
成功返回实际写入的字节数,write等于NULL时,将导致调用失败,并返回-EINVAL。
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
open域用来打开设备,并初始化设备,准备进行操作。如果该方法没有实现,系统
调用open也会是成功的,但驱动程序得不到任何打开设备的通知。在实现中,可以给出一定的提示信息。
int (*open) (struct inode *, struct file *);
release域用来关闭设备,释放设备资源。当且仅当结构struct file释放时被调用,
用来关闭一个文件或设备。
int (*release) (struct inode *, struct file *);
register_chrdev()和unregister_chrdev()
register_chrdev文件包含
#include <linux/fs.h>
device_unregister函数定义
static inline int register_chrdev(unsigned int major, const char *name,
const struct file_operations *fops)
- 函数register_chrdev()调用函数cdev_alloc()动态申请一个字符设备,调用函数cdev_add()将其加入Linux内核系统中。
register_chrdev输入参数说明
- 函数register_chrdev()有三个输入参数,第一个输入参数是unsigned int型的变量,代表动态申请字符设备的主设备号,对于此设备号函数自动赋值为0。
- 第二个输入参数是char型的指针,代表申请设备的设备名。
- 第三个输入参数是struct file_operations结构体类型的指针,代表申请设备的操作函数,通过此结构体包含的函数完成对设备的访问及控制操作,此结构体在函数cdev_init()的说明文档中已详细说明。
register_chrdev返回参数说明
- 函数register_chrdev()返回int型的结果,表示设备添加是否成功。如果成功返回0,如果失败返回-ENOMEM, ENOMEM的定义值为12。
unregister_chrdev文件包含
#include <linux/fs.h>
- 函数unregister_chrdev()通过调用函数__unregister_chrdev()实现其功能,函数__unregister_chrdev()首先调用函数__unregister_chrdev_region()删除一个字符设备区,并更改文件
/proc/devices
的内容;然后将一个字符设备从Linux内核系统中删除,如果此字符设备是通过函数cdev_alloc()动态申请的,函数会释放其占用的内存空间。最后调用函数cdev_del()删除字符设备。
unregister_chrdev输入参数说明
- 函数 unregister_chrdev()有两个输入参数,第一个输入参数代表即将被删除的字符设备区及字符设备的主设备号,函数将根据此参数查找内核中的字符设备。
- 第二个输入参数代表设备名,但在函数的实现源码中没有用到,没有什么意义。
unregister_chrdev返回参数说明
- 函数unregister_chrdev()的返回void类型的结果,即不返回任何类型的值。
unregister_chrdev函数定义
static inline void unregister_chrdev(unsigned int major, const char *name);
class_create()和class_destroy()
class_create文件包含
#include <linux/device.h>
- 宏class_create()用于动态创建设备的逻辑类,并完成部分字段的初始化,然后将其添加进Linux内核系统中。此函数的执行效果就是在目录
/sys/class
下创建一个新的文件夹,此文件夹的名字为此函数的第二个输入参数,但此文件夹是空的。宏class_create()在实现时,调用了函数__class_create(),作用和函数__class_create()基本相同。
struct class的name字段赋值。
class_create宏定义:
#define class_create(owner, name);
class_create输入参数说明
- 参数owner是一个struct module结构体类型的指针,指向函数__class_create()即将创建的struct class类型对象的拥有者,一般赋值为THIS_MODULE,此结构体的详细定义见文件linux-3.19.3/include/linux/module.h。
- 参数name是char类型的指针,代表即将创建的struct class变量的名字,用于给
class_create返回参数说明
- 宏class_create()的返回值与函数__class_create()的返回值相同,都代表新创建的逻辑类。此宏需要与函数class_destroy()配对使用,不能单独使用,当单独使用时,第一次不会出现错误,但当第二次插入模块时就会出现错误。
class_destroy文件包含
#include <linux/device.h>
- 函数class_destroy()用于删除设备的逻辑类,即从Linux内核系统中删除设备的逻辑类。此函数执行的效果是删除函数__class_create()或宏class_create()在目录
/sys/class
下创建的逻辑类对应的文件夹。
class_destroy函数定义
void class_destroy(struct class *cls)
class_destroy输入参数说明
- 参数owner是一个struct module结构体类型的指针,指向函数__class_create()即将创建的struct class类型对象的拥有者,一般赋值为THIS_MODULE,此结构体的详细定义见文件linux-3.19.3/include/linux/module.h。
- 参数name是char类型的指针,代表即将创建的struct class变量的名字,用于给struct class的name字段赋值。
class_destroy输入参数说明
- 函数
class_destroy()
的输入参数是struct class结构体类型的变量,代表设备的逻辑类。
class_destroy返回参数说明
- 函数class_destroy()的返回值是void类型的变量,即不返回任何值。
device_create()和device_destroy()
device_create文件包含
#include <linux/device.h>
函数device_create()用于动态地创建逻辑设备,并对新的逻辑设备类进行相应的初始化,将其与此函数的第一个参数所代表的逻辑类关联起来,然后将此逻辑设备加到Linux内核系统的设备驱动程序模型中。函数能够自动地在/sys/devices/virtual目录下创建新的逻辑设备目录,在/dev目录下创建与逻辑类对应的设备文件。
device_create函数定义
struct device *device_create(struct class *cls, struct device *parent,
dev_t devt,void *drvdata, const char *fmt, ...);
device_create输入参数说明
- 函数device_create()的第一个输入参数代表与即将创建的逻辑设备相关的逻辑类,
- 第二个输入参数代表即将创建的逻辑设备的父设备的指针,子设备与父设备的关系是:当父设备不可用时,子设备不可用,子设备依赖父设备,父设备不依赖子设备。
- 第三个输入参数是逻辑设备的设备号。
- 第四个输入参数是void类型的指针,代表回调函数的输入参数。
- 第五个输入参数是逻辑设备的设备名,即在目录/sys/devices/virtual创建的逻辑设备目录的目录名。
device_create返回参数说明
- 函数device_create()的返回值是struct device结构体类型的指针,指向新创建的逻辑设备。
device_unregister文件包含
#include <linux/device.h>
- 函数device_unregister()在实现过程中调用了函数device_del(),用于从Linux内核系统设备驱动程序模型中移除一个设备,并删除/sys/devices/virtual目录下对应的设备目录及/dev目录下对应的设备文件。
device_unregister函数定义
void device_unregister(struct device *dev);
device_unregister输入参数说明
- 参数dev是struct device结构体类型的指针,代表函数即将被删除的逻辑设备
device_unregister返回参数说明
- 函数device_unregister()的返回结果都是void类型的变量,即不返回任何值。