驅(qū)動(dòng)框架函數(shù)

構(gòu)造struct file_operations結(jié)構(gòu)體

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);
};

對(duì)于一個(gè)設(shè)備驅(qū)動(dòng)并不需要完成所有函數(shù)的映射,可以有選擇地進(jìn)行使用,下面對(duì)最常用的幾項(xiàng)進(jìn)行說(shuō)明:

這個(gè)域是用來(lái)設(shè)置指向“擁有”該結(jié)構(gòu)的模塊指針,內(nèi)核使用該指針維護(hù)模塊的使用計(jì)數(shù)。
struct module *owner;
read域用來(lái)從設(shè)備中讀數(shù)據(jù),需要提供字符串指針。從設(shè)備中讀取數(shù)據(jù)時(shí),
成功返回所讀取的字節(jié)數(shù),read等于NULL時(shí),將導(dǎo)致調(diào)用失敗,并返回-EINVAL。

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
write域用來(lái)向字符設(shè)備寫數(shù)據(jù),需要提供所寫指針內(nèi)容。當(dāng)向設(shè)備寫入數(shù)據(jù)時(shí),
成功返回實(shí)際寫入的字節(jié)數(shù),write等于NULL時(shí),將導(dǎo)致調(diào)用失敗,并返回-EINVAL。

ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
open域用來(lái)打開設(shè)備,并初始化設(shè)備,準(zhǔn)備進(jìn)行操作。如果該方法沒(méi)有實(shí)現(xiàn),系統(tǒng)
調(diào)用open也會(huì)是成功的,但驅(qū)動(dòng)程序得不到任何打開設(shè)備的通知。在實(shí)現(xiàn)中,可以給出一定的提示信息。

int (*open) (struct inode *, struct file *);
release域用來(lái)關(guān)閉設(shè)備,釋放設(shè)備資源。當(dāng)且僅當(dāng)結(jié)構(gòu)struct file釋放時(shí)被調(diào)用,
用來(lái)關(guān)閉一個(gè)文件或設(shè)備。

int (*release) (struct inode *, struct file *);

register_chrdev()和unregister_chrdev()

register_chrdev文件包含

#include <linux/fs.h>

device_unregister函數(shù)定義

static inline int register_chrdev(unsigned int major, const char *name,
                                    const struct file_operations *fops)
  • 函數(shù)register_chrdev()調(diào)用函數(shù)cdev_alloc()動(dòng)態(tài)申請(qǐng)一個(gè)字符設(shè)備,調(diào)用函數(shù)cdev_add()將其加入Linux內(nèi)核系統(tǒng)中。

register_chrdev輸入?yún)?shù)說(shuō)明

  • 函數(shù)register_chrdev()有三個(gè)輸入?yún)?shù),第一個(gè)輸入?yún)?shù)是unsigned int型的變量,代表動(dòng)態(tài)申請(qǐng)字符設(shè)備的主設(shè)備號(hào),對(duì)于此設(shè)備號(hào)函數(shù)自動(dòng)賦值為0。
  • 第二個(gè)輸入?yún)?shù)是char型的指針,代表申請(qǐng)?jiān)O(shè)備的設(shè)備名。
  • 第三個(gè)輸入?yún)?shù)是struct file_operations結(jié)構(gòu)體類型的指針,代表申請(qǐng)?jiān)O(shè)備的操作函數(shù),通過(guò)此結(jié)構(gòu)體包含的函數(shù)完成對(duì)設(shè)備的訪問(wèn)及控制操作,此結(jié)構(gòu)體在函數(shù)cdev_init()的說(shuō)明文檔中已詳細(xì)說(shuō)明。

register_chrdev返回參數(shù)說(shuō)明

  • 函數(shù)register_chrdev()返回int型的結(jié)果,表示設(shè)備添加是否成功。如果成功返回0,如果失敗返回-ENOMEM, ENOMEM的定義值為12。

unregister_chrdev文件包含

#include <linux/fs.h>
  • 函數(shù)unregister_chrdev()通過(guò)調(diào)用函數(shù)__unregister_chrdev()實(shí)現(xiàn)其功能,函數(shù)__unregister_chrdev()首先調(diào)用函數(shù)__unregister_chrdev_region()刪除一個(gè)字符設(shè)備區(qū),并更改文件/proc/devices的內(nèi)容;然后將一個(gè)字符設(shè)備從Linux內(nèi)核系統(tǒng)中刪除,如果此字符設(shè)備是通過(guò)函數(shù)cdev_alloc()動(dòng)態(tài)申請(qǐng)的,函數(shù)會(huì)釋放其占用的內(nèi)存空間。最后調(diào)用函數(shù)cdev_del()刪除字符設(shè)備。

unregister_chrdev輸入?yún)?shù)說(shuō)明

  • 函數(shù) unregister_chrdev()有兩個(gè)輸入?yún)?shù),第一個(gè)輸入?yún)?shù)代表即將被刪除的字符設(shè)備區(qū)及字符設(shè)備的主設(shè)備號(hào),函數(shù)將根據(jù)此參數(shù)查找內(nèi)核中的字符設(shè)備。
  • 第二個(gè)輸入?yún)?shù)代表設(shè)備名,但在函數(shù)的實(shí)現(xiàn)源碼中沒(méi)有用到,沒(méi)有什么意義。

unregister_chrdev返回參數(shù)說(shuō)明

  • 函數(shù)unregister_chrdev()的返回void類型的結(jié)果,即不返回任何類型的值。

unregister_chrdev函數(shù)定義

static inline void unregister_chrdev(unsigned int major, const char *name);

class_create()和class_destroy()

class_create文件包含

#include <linux/device.h>
  • class_create()用于動(dòng)態(tài)創(chuàng)建設(shè)備的邏輯類,并完成部分字段的初始化,然后將其添加進(jìn)Linux內(nèi)核系統(tǒng)中。此函數(shù)的執(zhí)行效果就是在目錄/sys/class下創(chuàng)建一個(gè)新的文件夾,此文件夾的名字為此函數(shù)的第二個(gè)輸入?yún)?shù),但此文件夾是空的。宏class_create()在實(shí)現(xiàn)時(shí),調(diào)用了函數(shù)__class_create(),作用和函數(shù)__class_create()基本相同。
    struct class的name字段賦值。

class_create宏定義:

#define class_create(owner, name);

class_create輸入?yún)?shù)說(shuō)明

  • 參數(shù)owner是一個(gè)struct module結(jié)構(gòu)體類型的指針,指向函數(shù)__class_create()即將創(chuàng)建的struct class類型對(duì)象的擁有者,一般賦值為THIS_MODULE,此結(jié)構(gòu)體的詳細(xì)定義見文件linux-3.19.3/include/linux/module.h。
  • 參數(shù)name是char類型的指針,代表即將創(chuàng)建的struct class變量的名字,用于給

class_create返回參數(shù)說(shuō)明

  • 宏class_create()的返回值與函數(shù)__class_create()的返回值相同,都代表新創(chuàng)建的邏輯類。此宏需要與函數(shù)class_destroy()配對(duì)使用,不能單獨(dú)使用,當(dāng)單獨(dú)使用時(shí),第一次不會(huì)出現(xiàn)錯(cuò)誤,但當(dāng)?shù)诙尾迦肽K時(shí)就會(huì)出現(xiàn)錯(cuò)誤。

class_destroy文件包含

#include <linux/device.h>
  • 函數(shù)class_destroy()用于刪除設(shè)備的邏輯類,即從Linux內(nèi)核系統(tǒng)中刪除設(shè)備的邏輯類。此函數(shù)執(zhí)行的效果是刪除函數(shù)__class_create()或宏class_create()在目錄/sys/class下創(chuàng)建的邏輯類對(duì)應(yīng)的文件夾。

class_destroy函數(shù)定義

void class_destroy(struct class *cls)

class_destroy輸入?yún)?shù)說(shuō)明

  • 參數(shù)owner是一個(gè)struct module結(jié)構(gòu)體類型的指針,指向函數(shù)__class_create()即將創(chuàng)建的struct class類型對(duì)象的擁有者,一般賦值為THIS_MODULE,此結(jié)構(gòu)體的詳細(xì)定義見文件linux-3.19.3/include/linux/module.h。
  • 參數(shù)name是char類型的指針,代表即將創(chuàng)建的struct class變量的名字,用于給struct class的name字段賦值。

class_destroy輸入?yún)?shù)說(shuō)明

  • 函數(shù)class_destroy()的輸入?yún)?shù)是struct class結(jié)構(gòu)體類型的變量,代表設(shè)備的邏輯類。

class_destroy返回參數(shù)說(shuō)明

  • 函數(shù)class_destroy()的返回值是void類型的變量,即不返回任何值。

device_create()和device_destroy()

device_create文件包含

#include <linux/device.h>

函數(shù)device_create()用于動(dòng)態(tài)地創(chuàng)建邏輯設(shè)備,并對(duì)新的邏輯設(shè)備類進(jìn)行相應(yīng)的初始化,將其與此函數(shù)的第一個(gè)參數(shù)所代表的邏輯類關(guān)聯(lián)起來(lái),然后將此邏輯設(shè)備加到Linux內(nèi)核系統(tǒng)的設(shè)備驅(qū)動(dòng)程序模型中。函數(shù)能夠自動(dòng)地在/sys/devices/virtual目錄下創(chuàng)建新的邏輯設(shè)備目錄,在/dev目錄下創(chuàng)建與邏輯類對(duì)應(yīng)的設(shè)備文件。

device_create函數(shù)定義

struct device *device_create(struct class *cls, struct device *parent,
                                    dev_t devt,void *drvdata, const char *fmt, ...);

device_create輸入?yún)?shù)說(shuō)明

  • 函數(shù)device_create()的第一個(gè)輸入?yún)?shù)代表與即將創(chuàng)建的邏輯設(shè)備相關(guān)的邏輯類,
  • 第二個(gè)輸入?yún)?shù)代表即將創(chuàng)建的邏輯設(shè)備的父設(shè)備的指針,子設(shè)備與父設(shè)備的關(guān)系是:當(dāng)父設(shè)備不可用時(shí),子設(shè)備不可用,子設(shè)備依賴父設(shè)備,父設(shè)備不依賴子設(shè)備。
  • 第三個(gè)輸入?yún)?shù)是邏輯設(shè)備的設(shè)備號(hào)。
  • 第四個(gè)輸入?yún)?shù)是void類型的指針,代表回調(diào)函數(shù)的輸入?yún)?shù)。
  • 第五個(gè)輸入?yún)?shù)是邏輯設(shè)備的設(shè)備名,即在目錄/sys/devices/virtual創(chuàng)建的邏輯設(shè)備目錄的目錄名。

device_create返回參數(shù)說(shuō)明

  • 函數(shù)device_create()的返回值是struct device結(jié)構(gòu)體類型的指針,指向新創(chuàng)建的邏輯設(shè)備。

device_unregister文件包含

#include <linux/device.h>
  • 函數(shù)device_unregister()在實(shí)現(xiàn)過(guò)程中調(diào)用了函數(shù)device_del(),用于從Linux內(nèi)核系統(tǒng)設(shè)備驅(qū)動(dòng)程序模型中移除一個(gè)設(shè)備,并刪除/sys/devices/virtual目錄下對(duì)應(yīng)的設(shè)備目錄及/dev目錄下對(duì)應(yīng)的設(shè)備文件。

device_unregister函數(shù)定義

void device_unregister(struct device *dev);

device_unregister輸入?yún)?shù)說(shuō)明

  • 參數(shù)dev是struct device結(jié)構(gòu)體類型的指針,代表函數(shù)即將被刪除的邏輯設(shè)備

device_unregister返回參數(shù)說(shuō)明

  • 函數(shù)device_unregister()的返回結(jié)果都是void類型的變量,即不返回任何值。

module_init() 和 module_exit()

MODULE_LICENSE("GPL");

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容