在學習字符設備驅動的開始,咱們必須瞭解的是三個很重要的數據結構,他們分別是file_operations、inode、file。下面陶毛毛同窗就和你們一塊兒來學習這三個數據結構。 node
struct _file_operations在Fs.h這個文件裏面被定義的,以下所示: 數據結構
struct file_operations {
struct module *owner;//擁有該結構的模塊的指針,通常爲THIS_MODULES
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 *);//向設備發送數據 appssize_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);//初始化一個異步的寫入操做
int (*readdir) (struct file *, void *, filldir_t);//僅用於讀取目錄,對於設備文件,該字段爲NULL
unsigned int (*poll) (struct file *, struct poll_table_struct *); //輪詢函數,判斷目前是否能夠進行非阻塞的讀寫或寫入
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); //執行設備I/O控制命令
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); //不使用BLK文件系統,將使用此種函數指針代替ioctl
long (*compat_ioctl) (struct file *, unsigned int, unsigned long); //在64位系統上,32位的ioctl調用將使用此函數指針代替
int (*mmap) (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 *, struct dentry *, int datasync); //刷新待處理的數據
int (*aio_fsync) (struct kiocb *, int datasync); //異步刷新待處理的數據
int (*fasync) (int, struct file *, int); //通知設備FASYNC標誌發生變化
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 **);
}; 異步Linux使用file_operations結構訪問驅動程序的函數,這個結構的每個成員的名字都對應着一個調用。用戶進程利用在對設備文件進行諸如read/write操做的時候,系統調用經過設備文件的主設備號找到相應的設備驅動程序,而後讀取這個數據結構相應的函數指針,接着把控制權交給該函數,這是Linux的設備驅動程序工做的基本原理。 async
下面是struct inode結構體。 函數
struct inode {
struct hlist_node i_hash; //哈希表
struct list_head i_list; //索引節點鏈表
struct list_head i_sb_list;//目錄項鍊表
struct list_head i_dentry;
unsigned long i_ino; //節點號
atomic_t i_count; //引用記數
unsigned int i_nlink; //硬連接數
uid_t i_uid; /*使用者id */
gid_t i_gid; /*使用者id組*/
dev_t i_rdev; //該成員表示設備文件的inode結構,它包含了真正的設備編號。
u64 i_version;
loff_t i_size; /*inode多表明的文件的大小*/
#ifdef __NEED_I_SIZE_ORDERED
seqcount_t i_size_seqcount;
#endif
struct timespec i_atime; /*inode最後一次存取的時間*/
struct timespec i_mtime; /*inode最後一次修改的時間*/
struct timespec i_ctime; /*inode的建立時間*/
unsigned int i_blkbits; /*inode在作I/O時的區塊大小*/
blkcnt_t i_blocks; /*inode所石油的block塊數*/
unsigned short i_bytes;
umode_t i_mode; /*inode的權限*/
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
struct mutex i_mutex;
struct rw_semaphore i_alloc_sem;
const struct inode_operations *i_op;
const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
struct super_block *i_sb;
struct file_lock *i_flock;
struct address_space *i_mapping;
struct address_space i_data;
#ifdef CONFIG_QUOTA
struct dquot *i_dquot[MAXQUOTAS];
#endif
struct list_head i_devices; /*如果字符設備,爲其對應的cdev結構體指針*/
union {
struct pipe_inode_info *i_pipe;
struct block_device *i_bdev; /*如果塊設備,爲其對應的cdev結構體指針*/
struct cdev *i_cdev; //該成員表示字符設備的內核的 內部結構。當inode指向一個字符設備文件時,該成員包含了指向struct cdev結構的指針,其中cdev結構是字符設備結構體。
};
int i_cindex;
__u32 i_generation;
#ifdef CONFIG_DNOTIFY
unsigned long i_dnotify_mask; /* Directory notify events */
struct dnotify_struct *i_dnotify; /* for directory notifications */
#endif
#ifdef CONFIG_INOTIFY
struct list_head inotify_watches; /* watches on this inode */
struct mutex inotify_mutex; /* protects the watches list */
#endif
unsigned long i_state;
unsigned long dirtied_when; /* jiffies of first dirtying */
unsigned int i_flags;
atomic_t i_writecount;
#ifdef CONFIG_SECURITY
void *i_security;
#endif
void *i_private; /* fs or device private pointer */
}; 學習
內核中用inode結構表示具體的文件,也就是對應與硬盤上面具體的文件。提供了設備文件的信息。inode譯成中文就是索引節點。每一個存儲設備或存儲設備的分區(存儲設備是硬盤、軟盤、U盤 ... ... )被格式化爲文件系統後,應該有兩部份,一部份是inode,另外一部份是Block,Block是用來存儲數據用的。而inode呢,就是用來存儲這些數據的信息,這些信息包括文件大小、屬主、歸屬的用戶組、讀寫權限等。inode爲每一個文件進行信息索引,因此就有了inode的數值。操做系統根據指令,能經過inode值最快的找到相對應的文件。 ui
最後是struct file。 this
struct file {
/*
* fu_list becomes invalid after file_free is called and queued via
* fu_rcuhead for RCU freeing
*/
union {
struct list_head fu_list;
struct rcu_head fu_rcuhead;
} f_u;
struct path f_path;
#define f_dentry f_path.dentry //該成員是對應的 目錄結構 。
#define f_vfsmnt f_path.mnt
const struct file_operations *f_op; //該操做 是定義文件關聯的操做的。內核在執行open時對這個指針賦值。
atomic_long_t f_count;//文件的引用計數(有多少進程打開該文件)
unsigned int f_flags; //該成員是文件標誌。
mode_t f_mode;//讀寫模式:open的mod_t mode參數
loff_t f_pos;//該文件在當前進程中的文件偏移量
struct fown_struct f_owner;//該結構的做用是經過信號進行I/O時間通知的數據
unsigned int f_uid, f_gid;//文件全部者id,全部者組id
struct file_ra_state f_ra; atom
u64 f_version;
#ifdef CONFIG_SECURITY
void *f_security;
#endif
/* needed for tty driver, and maybe others */
void *private_data;//該成員是系統調用時保存狀態信息很是有用的資源。
#ifdef CONFIG_EPOLL
/* Used by fs/eventpoll.c to link all the hooks to this file */
struct list_head f_ep_links;
spinlock_t f_ep_lock;
#endif /* #ifdef CONFIG_EPOLL */
struct address_space *f_mapping;
#ifdef CONFIG_DEBUG_WRITECOUNT
unsigned long f_mnt_write_state;
#endif
};
文件結構表明一個打開的文件描述符,它不是專門給驅動程序使用的,系統中每個打開的文件在內核中都有一個關聯的struct file。它由內核在open時建立,並傳遞給在文件上操做的任何函數,知道最後關閉。當文件的全部實例都關閉以後,內核釋放這個數據結構。
最後:總結一下,struct operations存在於設備驅動程序內部,起着聯繫應用程序和設備驅動的做用。struct inode存在於磁盤上,做爲描述設備驅動文件的信息的做用。struct file是在執行open函數時產生的,每打開一個文件就產生一個struct file,供設備驅動關聯的函數使用。