構(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類型的變量,即不返回任何值。