驱动框架函数

构造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类型的变量,即不返回任何值。

module_init() 和 module_exit()

MODULE_LICENSE("GPL");

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容